User Tools

Site Tools


сервис_asterisk

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
сервис_asterisk [2022/04/17 19:01]
val [Использование шаблонов в именах CHAN_SIP каналов]
сервис_asterisk [2025/08/27 11:36] (current)
val [Использование СУБД для хранения CDR]
Line 8: Line 8:
 ===== Установка ===== ===== Установка =====
  
 +  * [[https://​community.asterisk.org/​t/​install-asterisk-via-apt-or-from-source/​99713|Install Asterisk via apt or from source?]]
 ==== Debian/​Ubuntu ==== ==== Debian/​Ubuntu ====
 <​code>​ <​code>​
Line 38: Line 39:
 </​code><​code>​ </​code><​code>​
 [general] [general]
-;​udpbindaddr=0.0.0.0:​5061+;​udpbindaddr=0.0.0.0:​6050
 transport=udp transport=udp
 disallow=all disallow=all
 allow=alaw allow=alaw
  
-directmedia=no ​          ; for webinar +;directmedia=no ​          ; for nat 
-nat=force_rport,​comedia ​ ; for webinar+;nat=force_rport,​comedia ​ ; for nat 
 +;​qualify=yes ​             ; for nat
  
 ;​context=default ;​context=default
Line 72: Line 74:
 ;​disallow=all ;​disallow=all
 ;allow=gsm ;allow=gsm
-;​canreinvite=no ;1.4 
-;​directmedia=no ;1.6 
-;;;nat=yes 
-;​nat=force_rport,​comedia 
-;​qualify=yes 
 ;​call-limit=1 ;​call-limit=1
 ;​deny=0.0.0.0/​0.0.0.0 ;​deny=0.0.0.0/​0.0.0.0
 ;​permit=172.16.1.0/​255.255.255.0 ;​permit=172.16.1.0/​255.255.255.0
 +;​directmedia=no
 +;​nat=force_rport,​comedia
 +;​qualify=yes
  
 ;[user2] ;[user2]
Line 110: Line 110:
 directmedia=no directmedia=no
 ;​call-limit=1 ;​call-limit=1
 +;​transport=tls
 +;​encryption=yes
  
 [401](office) [401](office)
Line 132: Line 134:
   * Переменные канала:​ [[https://​wiki.asterisk.org/​wiki/​display/​AST/​Asterisk+13+Function_PJSIP_ENDPOINT|function '​PJSIP_ENDPOINT'​]]   * Переменные канала:​ [[https://​wiki.asterisk.org/​wiki/​display/​AST/​Asterisk+13+Function_PJSIP_ENDPOINT|function '​PJSIP_ENDPOINT'​]]
   * [[https://​zadarma.com/​ru/​support/​instructions/​asteriskpjsip/​|Пример настройки подключения Asterisk PJSIP к Zadarma]]   * [[https://​zadarma.com/​ru/​support/​instructions/​asteriskpjsip/​|Пример настройки подключения Asterisk PJSIP к Zadarma]]
 +  * [[https://​voxlink.ru/​kb/​asterisk-configuration/​opisanie-parametrov-konfiguracii-pjsip-v-asterisk-s-primerami/​|Описание параметров конфигурации PJSIP в Asterisk с примерами]]
  
 === Настройка PJSIP транспорта === === Настройка PJSIP транспорта ===
Line 138: Line 141:
 </​code><​code>​ </​code><​code>​
 [general] [general]
-udpbindaddr=0.0.0.0:​5061+udpbindaddr=0.0.0.0:​6050
 </​code><​code>​ </​code><​code>​
 # cat /​etc/​asterisk/​pjsip.conf # cat /​etc/​asterisk/​pjsip.conf
Line 150: Line 153:
 === Настройка PJSIP точки подключения телефона === === Настройка PJSIP точки подключения телефона ===
  
-Базовый вариант+== Базовый вариант ​==
  
 <​code>​ <​code>​
Line 176: Line 179:
 max_contacts=1 max_contacts=1
 remove_existing=yes remove_existing=yes
 +mailboxes=401@corpX
 ;​qualify_frequency=60 ;​qualify_frequency=60
 +
  
 [401] [401]
Line 186: Line 191:
 </​code>​ </​code>​
  
-Wizard вариант+== Вариант с шаблонами == 
 +<​code>​ 
 +# cat /​etc/​asterisk/​pjsip.conf 
 +</​code><​code>​ 
 +... 
 +[endpoint-office](!) 
 +type=endpoint 
 +transport=udp-transport-1 
 +context=default 
 +disallow=all 
 +allow=alaw 
 +[aor-reg](!) 
 +type=aor 
 +max_contacts=1 
 +remove_existing=yes 
 +[auth-userpass](!) 
 +type = auth 
 +auth_type = userpass 
 + 
 +[401](endpoint-office) 
 +aors=401 
 +auth=401 
 +callerid=Иван Иванов<​401>​ 
 +[401](aor-reg) 
 +mailboxes=401@corp13 
 +[401](auth-userpass) 
 +password=tpassword401 
 +username=401 
 + 
 +[403](endpoint-office) 
 +aors=403 
 +auth=403 
 +callerid=Вячеслав Лохтуров<​403>​ 
 +[403](aor-reg) 
 +mailboxes=403@corp13 
 +[403](auth-userpass) 
 +password=tpassword403 
 +username=403 
 +... 
 +</​code>​ 
 + 
 +== Wizard вариант ​==
  
 !!! Изменение отдельных параметров требует либо удаление/​reload/​добавление/​reload всего описания точки подключения,​ либо перезапуска asterisk !!! Изменение отдельных параметров требует либо удаление/​reload/​добавление/​reload всего описания точки подключения,​ либо перезапуска asterisk
Line 203: Line 249:
 ;​endpoint/​set_var=MY-USER-ID=user2@corp13.un ;​endpoint/​set_var=MY-USER-ID=user2@corp13.un
 ;​endpoint/​callerid=Petr P. Petrov<​402>​ ;​endpoint/​callerid=Petr P. Petrov<​402>​
 +;​endpoint/​force_rport=yes
 +;​endpoint/​rewrite_contact=yes
 +;​endpoint/​rtp_symmetric=yes
 +;​endpoint/​direct_media=no
 +;​endpoint/​acl=acl_office
 +;;​endpoint/​acl=acl_internet
 aor/​max_contacts=1 aor/​max_contacts=1
 aor/​remove_existing=yes aor/​remove_existing=yes
 +</​code><​code>​
 +# cat /​etc/​asterisk/​acl.conf
 +</​code><​code>​
 +[acl_office]
 +deny=0.0.0.0/​0.0.0.0
 +permit=192.168.X.0/​255.255.255.0
 +
 +[acl_internet]
 +permit=0.0.0.0/​0.0.0.0
 </​code>​ </​code>​
  
Line 359: Line 420:
 </​code><​code>​ </​code><​code>​
 [general] [general]
 +...
 +disallow=all
 +allow=alaw
 ... ...
 allow=h263 allow=h263
Line 368: Line 432:
  
 ==== Отладка работы Asterisk ==== ==== Отладка работы Asterisk ====
 +
 +  * [[https://​community.asterisk.org/​t/​help-new-installation-full-of-errors/​46614|HELP - New Installation Full of Errors]]
  
 === Сервисные сообщения === === Сервисные сообщения ===
Line 386: Line 452:
 </​code><​code>​ </​code><​code>​
 # tail -f /​var/​log/​asterisk/​messages # tail -f /​var/​log/​asterisk/​messages
 +
 +ubuntu24# tail -f /​var/​log/​asterisk/​messages.log
 </​code>​ </​code>​
  
Line 419: Line 487:
  
 ;[incoming] ;[incoming]
 +;exten => voip1_00000X,​1,​Dial(...)
  
 include=>​incoming_work_time,​10:​00-16:​59,​mon-fri,​*,​* include=>​incoming_work_time,​10:​00-16:​59,​mon-fri,​*,​*
Line 476: Line 545:
 ;register => 00000X:​spasswordX@voip1.un/​voip1_00000X ;register => 00000X:​spasswordX@voip1.un/​voip1_00000X
 ... ...
 +;​[trunk_voip1_00000X]
 +;​qualify=yes
 [voip1_00000X] [voip1_00000X]
 type=peer type=peer
Line 486: Line 557:
 insecure=invite insecure=invite
 callbackextension=voip1_00000X callbackextension=voip1_00000X
 +;​callbackextension=exten_voip1_00000X
 </​code><​code>​ </​code><​code>​
 server# cat /​etc/​asterisk/​extensions.conf server# cat /​etc/​asterisk/​extensions.conf
Line 502: Line 574:
 exten => voip1_00000X,​1,​Dial(SIP/​401&​SIP/​402&​SIP/​403&​SIP/​404) exten => voip1_00000X,​1,​Dial(SIP/​401&​SIP/​402&​SIP/​403&​SIP/​404)
  
-;exten => voip1_00000X,​1,​Dial(${MY-RING-GROUP})+;exten => exten_voip1_00000X,​1,​Dial(${MY-RING-GROUP})
  
 ;exten => 8495XXXXXXX,​1,​Dial(${MY-RING-GROUP-${EXTEN}}) ;exten => 8495XXXXXXX,​1,​Dial(${MY-RING-GROUP-${EXTEN}})
Line 666: Line 738:
 ==== Просмотр текущих звонков ==== ==== Просмотр текущих звонков ====
 <​code>​ <​code>​
 +server*CLI>​ core show channels
 +
 server*CLI>​ sip show channels server*CLI>​ sip show channels
  
Line 747: Line 821:
 === Создание базы данных === === Создание базы данных ===
  
-  * [[https://wiki.asterisk.org/​wiki/display/AST/MySQL+CDR+Backend|MySQL CDR Backend]]+  * [[https://community.asterisk.org/​t/howto-cdr-with-mysql/20505|HOWTO: ​CDR with MySQL]]
  
 <​code>​ <​code>​
Line 754: Line 828:
 CREATE DATABASE asterisk; CREATE DATABASE asterisk;
    
-GRANT ALL ON asterisk.* TO asterisk@localhost IDENTIFIED BY '​asterisk';​+CREATE USER asterisk@localhost IDENTIFIED BY '​asterisk';​ 
 + 
 +GRANT ALL ON asterisk.* TO asterisk@localhost;​ 
 + 
 +#GRANT ALL ON asterisk.* TO asterisk@localhost IDENTIFIED BY '​asterisk';​
  
 USE asterisk; USE asterisk;
Line 800: Line 878:
 exten => _4XX,​1,​GoSub(sub-monitor,​s,​1) exten => _4XX,​1,​GoSub(sub-monitor,​s,​1)
 exten => _4XX,​n,​Dial(SIP/​${EXTEN}) exten => _4XX,​n,​Dial(SIP/​${EXTEN})
 +...
 +exten => _8XXXXXXXXXX,​1,​GoSub(sub-monitor,​s,​1)
 +exten => _8XXXXXXXXXX,​n,​Dial(...)
 ... ...
 ;​[macro-monitor] ;​[macro-monitor]
Line 839: Line 920:
 <​code>​ <​code>​
 http://​172.16.1.X/​asterisk-cdr-viewer/​ http://​172.16.1.X/​asterisk-cdr-viewer/​
 +</​code>​
 +
 +  * Спасибо Комлеву Александру Павловичу! ​
 +
 +<​code>​
 +Чтобы запись разговора воспроизводилась прямо на странице CDR Viewer, нужно в файле ​
 +/​var/​www/​html/​asterisk-cdr-viewer/​include/​functions.inc.php
 +заменить ​ строку:​
 +
 +echo " ​   <td class=\"​record_col\"><​a href=\"​download.php?​audio=$recorded_file.$system_audio_format\"​ title=\"​Listen to call recording\"><​img src=\"​templates/​images/​sound.png\"​ alt=\"​Call recording\"​ /></​a></​td>​\n";​
 +
 +на такую:
 +
 +echo " ​   <td class=\"​record_col\"><​a href=\"​download.php?​audio=$recorded_file.$system_audio_format\"​ title=\"​Listen to call recording\"><​img src=\"​templates/​images/​sound.png\"​ alt=\"​Call recording\"​ /></​a><​audio controls><​source src=\"​download.php?​audio=$recorded_file.$system_audio_format\"></​audio></​td>​\n";​
 +
 </​code>​ </​code>​
 ===== Asterisk realtime ===== ===== Asterisk realtime =====
Line 1473: Line 1569:
 dsn=asterisk dsn=asterisk
 readsql=SELECT dstchannel FROM cdr WHERE src='​${ARG1}'​ AND disposition='​ANSWERED'​ ORDER BY calldate DESC LIMIT 1; readsql=SELECT dstchannel FROM cdr WHERE src='​${ARG1}'​ AND disposition='​ANSWERED'​ ORDER BY calldate DESC LIMIT 1;
 +
 +
 </​code><​code>​ </​code><​code>​
 # cat /​etc/​asterisk/​extensions.conf # cat /​etc/​asterisk/​extensions.conf
Line 1484: Line 1582:
 ... ...
 </​code>​ </​code>​
-===== Аутентификация и учет звонков в RADIUS ===== 
  
-  * [[Сервис FreeRADIUS]] 
- 
-<​code>​ 
-# cat /​usr/​share/​auth.sh 
-</​code><​code>​ 
-#!/bin/sh 
- 
-CALL_FROM=$1 
- 
-# chown asterisk /​tmp/​auth.log 
- 
-if echo "​User-Name=${CALL_FROM},​User-Password=${CALL_FROM},​NAS-IP-Address=127.0.0.1"​ | radclient localhost auth testing123 >>/​tmp/​auth.log 
-then 
-        echo -n YES 
-else 
-        echo -n NO 
-fi 
- 
-exit 0 
-</​code><​code>​ 
-# cat /​usr/​share/​acct-start.sh 
-</​code><​code>​ 
-#!/bin/sh 
- 
-CALL_ID=$1 
-CALL_FROM=$2 
-CALL_TO=$3 
- 
-echo "​User-Name=${CALL_FROM},​Acct-Session-Id=${CALL_ID},​Called-Station-Id=${CALL_TO},​Calling-Station-Id=${CALL_FROM},​Acct-Status-Type=Start,​NAS-IP-Address=127.0.0.1,​NAS-Port=${CALL_FROM}${CALL_TO}"​| radclient localhost acct testing123 
- 
-exit 0 
-</​code><​code>​ 
-# cat /​usr/​share/​acct-stop.sh 
-</​code><​code>​ 
-#!/bin/sh 
- 
-CALL_ID=$1 
-CALL_FROM=$2 
-CALL_TO=$3 
- 
-echo "​User-Name=${CALL_FROM},​Acct-Session-Id=${CALL_ID},​Acct-Status-Type=Stop,​NAS-IP-Address=127.0.0.1,​NAS-Port=${CALL_FROM}${CALL_TO}"​| radclient localhost acct testing123 
- 
-exit 0 
-</​code>​ 
- 
-Примечания:​ 
- 
-  * Помещаем абонента,​ звонки которого надо тарифицировать,​ в контекст billing 
-  * Переводим все тарифицируемые вызовы в контекст aaa-call (что-бы отследить событие окончания разговора через контекст "​h"​) 
-  * В случае MYAUTH!=NO разрешаем абоненту совершить звонок. С помощью макроса "​U"​ программируем вызов кода в момент снятия трубки для начала тарификации. По какой то причине переменные ${CALLERID(num)} ${CALLERID(dnid)} не передаются,​ а ${UNIQUEID} меняет значение в этом коде, поэтому занчения передаются через аргументы. 
-  * В контексте "​h"​ проверяем факт наличия разговора и только в этом случае тарифицируем его окончание 
- 
-<​code>​ 
-# cat /​etc/​asterisk/​extensions.conf 
-</​code><​code>​ 
-... 
-[billing] 
-... 
-exten => _4XX,​1,​Goto(aaa-call,​s,​1) 
-... 
-[aaa-call] 
-exten => s,​1,​Verbose(AUTH CALL_ID=${UNIQUEID} CALL_FROM=${CALLERID(num)} CALL_TO=${CALLERID(dnid)}) 
-exten => s,​n,​Set(MYAUTH=${SHELL(/​usr/​share/​auth.sh ${CALLERID(num)})});​ 
-exten => s,​n,​GotoIf($["​${MYAUTH}"​ = "​NO"​]?​end_call) 
-exten => s,​n,​Dial(SIP/​${CALLERID(dnid)},,​U(aaa-call-beg-acct,​${UNIQUEID},​${CALLERID(num)},​${CALLERID(dnid)}));​ 
-exten => s,​n(end_call),​Hangup() 
- 
-exten => h,​1,​GotoIf($["​${DIALSTATUS}"​ != "​ANSWER"​]?​no-answer) 
-exten => h,​n,​Verbose(END ACCT DIALSTATUS=${DIALSTATUS} CALL_ID=${UNIQUEID} CALL_FROM=${CALLERID(num)} CALL_TO=${CALLERID(dnid)}) 
-exten => h,​n,​System(/​usr/​share/​acct-stop.sh ${UNIQUEID} ${CALLERID(num)} ${CALLERID(dnid)}) 
-exten => h,​n(no-answer),​NoOp() 
- 
-[aaa-call-beg-acct] 
-exten => s,​1,​Verbose(BEGIN ACCT CALL_ID=${ARG1} CALL_FROM=${ARG2} CALL_TO=${ARG3}) 
-exten => s,​n,​System(/​usr/​share/​acct-start.sh ${ARG1} ${ARG2} ${ARG3}) 
-exten => s,n,return 
-... 
-</​code>​ 
 ===== Настройка дополнительных видов обслуживания ===== ===== Настройка дополнительных видов обслуживания =====
  
Line 1593: Line 1612:
 [general] [general]
 ... ...
-;featuredigittimeout = 1000+featuredigittimeout = 3000
 ... ...
 [featuremap] [featuremap]
Line 1683: Line 1702:
 ... ...
 pickupexten = *88 pickupexten = *88
-... 
-</​code><​code>​ 
-server# cat /​etc/​asterisk/​extensions.conf 
-</​code><​code>​ 
-... 
-exten => _8XXXXXXXXXX,​1,​Dial(SIP/​voip1_00000X/​${EXTEN},,​T) 
-... 
-exten => voip1_00000X,​1,​Dial(SIP/​401,,​t) 
 ... ...
 </​code><​code>​ </​code><​code>​
Line 1717: Line 1728:
  
 include => parkedcalls include => parkedcalls
 +...
 +exten => _8XXXXXXXXXX,​1,​Dial(SIP/​voip1_00000X/​${EXTEN},,​T)
 +...
 +exten => voip1_00000X,​1,​Dial(SIP/​401,,​t)
 ... ...
 </​code>​ </​code>​
Line 1783: Line 1798:
  
 ===== Голосовая почта ===== ===== Голосовая почта =====
 +
 +  * [[https://​community.asterisk.org/​t/​no-application-voicemail/​99717|No application ‘VoiceMail’]]
  
 <​code>​ <​code>​
 +ubuntu24# cat /​etc/​asterisk/​modules.conf
 +</​code><​code>​
 +...
 +[modules]
 +
 +;noload => app_voicemail.so
 +noload => app_voicemail_imap.so
 +noload => app_voicemail_odbc.so
 +noload => res_pjsip_send_to_voicemail.so
 +;;;​server*CLI>​ module show like voicemail
 +...
 +</​code><​code>​
 server# cat /​etc/​asterisk/​voicemail.conf server# cat /​etc/​asterisk/​voicemail.conf
 </​code><​code>​ </​code><​code>​
Line 1806: Line 1835:
 ;;;debian# service asterisk restart ;;;debian# service asterisk restart
 ;​imapserver=server.corpX.un ;​imapserver=server.corpX.un
 +;​imapserver=localhost
 +;​imapflags=notls
 ;​imapfolder=INBOX ;​imapfolder=INBOX
 +
  
 ;;;For SMTP ;;;For SMTP
Line 1828: Line 1860:
  
 ;exten => 391,​1,​VoiceMailMain(${CALLERID(num)}@corpX) ;exten => 391,​1,​VoiceMailMain(${CALLERID(num)}@corpX)
-;exten => asterisk,​1,​VoiceMailMain(${CALLERID(num)}@corpX)+;exten => asterisk,​1,​VoiceMailMain(${CALLERID(num)}@corpX) ​ ;new Zoiper, PhonerLite
 ... ...
 exten => _4XX,​1,​Dial(SIP/​${EXTEN},​10,​Tt) exten => _4XX,​1,​Dial(SIP/​${EXTEN},​10,​Tt)
Line 1911: Line 1943:
 server*CLI>​ channel originate SIP/403 extension 89161234567@default server*CLI>​ channel originate SIP/403 extension 89161234567@default
  
-; Сначала вызов абонента,​ затем обработчика ​(например - IVR)+; Сначала вызов абонента,​ затем обработчиканапример - IVR (не работает с текущим провайдером,​  
 +; можно использовать call файлы, или AMI/ARI, где есть возможность указать CallerId)
 server*CLI>​ channel originate SIP/​voip1_00000X/​89161234567 extension voip1_00000X@default server*CLI>​ channel originate SIP/​voip1_00000X/​89161234567 extension voip1_00000X@default
 server*CLI>​ channel originate PJSIP/​89161234567@voip1_00000X extension voip1_00000X@default server*CLI>​ channel originate PJSIP/​89161234567@voip1_00000X extension voip1_00000X@default
  
-; сначала вызов обработчика (например - все телефоны в офисе или оператор/​агент из членов очереди),​ затем вызов абонента+; сначала вызов обработчика (например - все телефоны в офисе или оператор/​агент из членов очереди), ​ 
 +затем вызов абонента ​(работает с текущим провайдером)
 server*CLI>​ channel originate Local/​voip1_00000X@default extension 89161234567@default server*CLI>​ channel originate Local/​voip1_00000X@default extension 89161234567@default
 </​code><​code>​ </​code><​code>​
Line 1929: Line 1963:
 ==== С использованием Call файлов ==== ==== С использованием Call файлов ====
  
-  * [[http://wiki.pro-voip.ru/asterisk/asterisk-call-files.html|Синтаксис вызова ​Asterisk Call Files]]+  * [[https://docs.asterisk.org/Configuration/Interfaces/​Asterisk-Call-Files/|Asterisk Call Files]]
   * [[Сервис atrun]]   * [[Сервис atrun]]
  
Line 1940: Line 1974:
 CallerId: CorpX<​84992636363>​ CallerId: CorpX<​84992636363>​
 </​code><​code>​ </​code><​code>​
 +server# grep astspooldir /​etc/​asterisk/​asterisk.conf
 +
 server# cp call.txt /​var/​spool/​asterisk/​outgoing/​ server# cp call.txt /​var/​spool/​asterisk/​outgoing/​
 +
 +debian11# ls /​var/​spool/​asterisk/​outgoing_done
 </​code><​code>​ </​code><​code>​
 # cat /​usr/​share/​originate_call_file.sh # cat /​usr/​share/​originate_call_file.sh
Line 2031: Line 2069:
 ;[menu2] ;[menu2]
 ;exten => s,​1,​Background(silence/​8) ;exten => s,​1,​Background(silence/​8)
-;exten => s,1,​WaitExten(8) ​   ; работает только после Answer или Background+;exten => s,n,​WaitExten(8) ​   ; работает только после Answer или Background
 ;exten => _4XX,​1,​Goto(default,​${EXTEN},​1) ;exten => _4XX,​1,​Goto(default,​${EXTEN},​1)
 ;exten => t,​1,​Goto(menu,​s,​1) ​ ; timeout exceeded, работает только с WaitExten ;exten => t,​1,​Goto(menu,​s,​1) ​ ; timeout exceeded, работает только с WaitExten
Line 2092: Line 2130:
 ... ...
 exten => _5XX/​402,​1,​ChanSpy(SIP/​4${EXTEN:​1},​qw) exten => _5XX/​402,​1,​ChanSpy(SIP/​4${EXTEN:​1},​qw)
 +
 +;exten => _5XX,​1,​Verbose(1,​Значение CALLERID равно ${CALLERID(number)})
 +;exten => _5XX,​n,​ChanSpy(SIP/​4${EXTEN:​1},​qw)
 ... ...
 </​code>​ </​code>​
Line 2101: Line 2142:
   * Если создается два файла - in и out, то ([[http://​asterisk.ru/​knowledgebase/​Asterisk+config+features.conf|можно смикшировать в один, используя утилиту sox]])   * Если создается два файла - in и out, то ([[http://​asterisk.ru/​knowledgebase/​Asterisk+config+features.conf|можно смикшировать в один, используя утилиту sox]])
   * [[http://​asterisk-support.ru/​question/​59823/​touch-mix-monitor-prefiks/​|touch mix monitor префикс]]   * [[http://​asterisk-support.ru/​question/​59823/​touch-mix-monitor-prefiks/​|touch mix monitor префикс]]
-  ​+ 
 +  * [[https://​docs.asterisk.org/​Configuration/​Features/​One-Touch-Features/​]] 
 +  * [[https://​community.asterisk.org/​t/​verify-if-mixmonitor-is-already-running/​89144|Verify if MixMonitor is already running]]
  
 <​code>​ <​code>​
Line 2110: Line 2153:
 ... ...
 automon => *11 automon => *11
 +...
 +;automixmon => *3
 ... ...
 </​code><​code>​ </​code><​code>​
Line 2117: Line 2162:
 exten => _4XX,​n,​Set(TOUCH_MONITOR=${STRFTIME(${EPOCH},,​%Y.%m.%d-%H.%M)}_${CALLERID(number)}_${EXTEN}) exten => _4XX,​n,​Set(TOUCH_MONITOR=${STRFTIME(${EPOCH},,​%Y.%m.%d-%H.%M)}_${CALLERID(number)}_${EXTEN})
 exten => _4XX,​n,​Dial(SIP/​${EXTEN},,​wW) exten => _4XX,​n,​Dial(SIP/​${EXTEN},,​wW)
 +;exten => _4XX,​n,​Set(TOUCH_MIXMONITOR=${STRFTIME(${EPOCH},,​%Y.%m.%d-%H.%M)}_${CALLERID(number)}_${EXTEN})
 +;exten => _4XX,​n,​Dial(SIP/​${EXTEN},,​xX)
 ... ...
 exten => _8XXXXXXXXXX,​1,​Set(TOUCH_MONITOR=${STRFTIME(${EPOCH},,​%Y.%m.%d-%H.%M)}_${CALLERID(number)}_${EXTEN}) exten => _8XXXXXXXXXX,​1,​Set(TOUCH_MONITOR=${STRFTIME(${EPOCH},,​%Y.%m.%d-%H.%M)}_${CALLERID(number)}_${EXTEN})
 exten => _8XXXXXXXXXX,​n,​Dial(SIP/​voip1_00000X/​${EXTEN},,​W) exten => _8XXXXXXXXXX,​n,​Dial(SIP/​voip1_00000X/​${EXTEN},,​W)
-..+;exten => _8XXXXXXXXXX,​1,​Set(TOUCH_MIXMONITOR=${STRFTIME(${EPOCH},,​%Y.%m.%d-%H.%M)}_${CALLERID(number)}_${EXTEN}) 
 +;exten => _8XXXXXXXXXX,​n,​Dial(SIP/​voip1_00000X/​${EXTEN},,​X) 
 +...
 </​code><​code>​ </​code><​code>​
 server*CLI>​ core reload server*CLI>​ core reload
Line 2176: Line 2225:
  
 <​code>​ <​code>​
-server# ​mkdir /​usr/​share/​asterisk/​incoming+server# ​
  
-server# ​cp -v /​usr/​share/​asterisk/​sounds/​recordings/speech.alaw /​usr/​share/​asterisk/​incoming/+mkdir /​usr/​share/​asterisk/​busy/​ 
 +cp -v /​usr/​share/​asterisk/​sounds/​ru/tt-allbusy./​usr/​share/​asterisk/​busy/
  
-server# ​mkdir /​usr/​share/​asterisk/​busy/+mkdir /​usr/​share/​asterisk/​incoming 
 +cp -v /​usr/​share/​asterisk/​sounds/​recordings/​speech.alaw /​usr/​share/​asterisk/​incoming/
  
-server# cp -v /​usr/​share/​asterisk/​sounds/​ru/​tt-allbusy.* /​usr/​share/​asterisk/​busy/​ +mkdir /​usr/​share/​asterisk/​silence/​ 
- +cp -v /​usr/​share/​asterisk/​sounds/​en/​silence/​10.* /​usr/​share/​asterisk/​silence/​
-server# ​mkdir /​usr/​share/​asterisk/​silence/​ +
- +
-server# ​cp -v /​usr/​share/​asterisk/​sounds/​en/​silence/​10.* /​usr/​share/​asterisk/​silence/​+
  
 server# cat /​etc/​asterisk/​musiconhold.conf server# cat /​etc/​asterisk/​musiconhold.conf
 </​code><​code>​ </​code><​code>​
 ... ...
 +[busy]
 +mode=files
 +directory=busy
 +
 [incoming] [incoming]
 mode=files mode=files
 directory=incoming directory=incoming
- 
-[busy] 
-mode=files 
-directory=busy 
  
 [silence] [silence]
Line 2206: Line 2254:
 </​code><​code>​ </​code><​code>​
 ... ...
-exten => voip1_00000X,​1,​Dial(SIP/​4NN,,​m(incoming)t)+exten => voip1_00000X,​1,Answer() 
 +exten => voip1_00000X,​n,​Dial(SIP/​4NN,,​m(incoming)t)
 </​code>​ </​code>​
 ===== Синтез речи с использованием пакета Festival ===== ===== Синтез речи с использованием пакета Festival =====
Line 2247: Line 2296:
 ;exten => _4XX,​n,​Set(MY-CALLED-USER-NAME=${ODBC_SIPFRIENDS_BY_NAME(${EXTEN})}) ;exten => _4XX,​n,​Set(MY-CALLED-USER-NAME=${ODBC_SIPFRIENDS_BY_NAME(${EXTEN})})
 exten => _4XX,​n,​Set(MY-CALLED-USER-NAME=${SIPPEER(${EXTEN},​callerid_name)}) exten => _4XX,​n,​Set(MY-CALLED-USER-NAME=${SIPPEER(${EXTEN},​callerid_name)})
-;exten => _4XX,​n,​Set(MY-CALLED-USER-NAME=${PJSIP_ENDPOINT(${EXTEN},​callerid)})+;exten => _4XX,​n,​Set(MY-CALLED-USER-NAME=${CUT(PJSIP_ENDPOINT(${EXTEN},​callerid),\",2)})
  
 exten => _4XX,​n,​Festival(${MY-CALLED-USER-NAME} не может ответить) exten => _4XX,​n,​Festival(${MY-CALLED-USER-NAME} не может ответить)
Line 2259: Line 2308:
 server# cat /​etc/​asterisk/​followme.conf server# cat /​etc/​asterisk/​followme.conf
 </​code><​code>​ </​code><​code>​
 +;...
 [101+X] [101+X]
 ;​number=>​401,​30 ;​number=>​401,​30
 ;​number=>​89162323232,​30 ;​number=>​89162323232,​30
 context=>​default context=>​default
 +;​context=>​to-pstn
 [401] [401]
 number=>​89162323232,​30 number=>​89162323232,​30
 ;​number=>​89163434345,​30 ;​number=>​89163434345,​30
 context=>​default context=>​default
 +;​context=>​to-pstn
 </​code><​code>​ </​code><​code>​
 server# cat /​etc/​asterisk/​extensions.conf server# cat /​etc/​asterisk/​extensions.conf
Line 2409: Line 2461:
 exten => s,​n,​ExecIf($["​${DIALSTATUS}"​="​${BUSY}"​]?​Bridge(SIP/​854)) exten => s,​n,​ExecIf($["​${DIALSTATUS}"​="​${BUSY}"​]?​Bridge(SIP/​854))
 exten => s,​n,​Dial(SIP/​854) exten => s,​n,​Dial(SIP/​854)
 +</​code>​
 +
 +Кузьмин Алексей предложил решение,​ если требуется только уведомить звонящего
 +
 +<​code>​
 +exten => _X.,​1,​Dial(PJSIP/​${EXTEN},​60)
 +exten => _X.,​n,​Goto(s-${DIALSTATUS},​1) ; Jump based on status (NOANSWER, BUSY, CHANUNAVAIL,​ CONGESTION, ANSWER)
 +exten => s-BUSY,​1,​Playback(ru/​custom/​busy_ru)
 +exten => s-BUSY,​n,​Hangup()
 +exten => s-NOANSWER,​1,​Playback(ru/​custom/​noanswer_ru)
 +exten => s-NOANSWER,​n,​Hangup()
 +exten => s-CHANUNAVAIL,​1,​Playback(ru/​custom/​invalid_ru)
 +exten => s-CHANUNAVAIL,​n,​Hangup()
 </​code>​ </​code>​
 ===== Организация Call центра ===== ===== Организация Call центра =====
Line 2426: Line 2491:
  
 [queue1] [queue1]
-;для демонстрации на многоканальном телефоне установить call-limit=1 +;timeout=10 
-;member => SIP/401  ​в вебинаре (занять можно звонком на 311) + 
-;member => SIP/403  ​в классе+;member => SIP/403 
 + 
 +;member => SIP/​user1@mailcgp 
 +;member => SIP/user2@mailcgp 
 +;member => SIP/​user3@mailcgp
 </​code><​code>​ </​code><​code>​
 sever# cat /​etc/​asterisk/​extensions.conf sever# cat /​etc/​asterisk/​extensions.conf
Line 2479: Line 2548:
 strategy = rrmemory strategy = rrmemory
 musicclass = default musicclass = default
-timeout=10 
  
 announce = queue-markq announce = queue-markq
Line 2489: Line 2557:
 member => Local/​802@agents member => Local/​802@agents
 member => Local/​803@agents member => Local/​803@agents
- 
-;member => SIP/​user1@mailcgp 
-;member => SIP/​user2@mailcgp 
-;member => SIP/​user3@mailcgp 
 </​code><​code>​ </​code><​code>​
 server*CLI>​ queue show queue1 server*CLI>​ queue show queue1
Line 2529: Line 2593:
 # cat /​var/​www/​html/​asterisk/​addrbook.txt # cat /​var/​www/​html/​asterisk/​addrbook.txt
 </​code><​code>​ </​code><​code>​
-Вячеслав Лохтуров<​+74951234569+Вячеслав Лохтуров<​84951234569
-Вячеслав Лохтуров<​+74951234560+Вячеслав Лохтуров<​84951234560
-Ваше ФИО<+7ВАШМОБИЛЬНЫЙ>​+Ваше ФИО<8ВАШМОБИЛЬНЫЙ>​
 </​code><​code>​ </​code><​code>​
 # cat /​usr/​local/​bin/​get-customer-callerid-all.sh # cat /​usr/​local/​bin/​get-customer-callerid-all.sh
Line 2561: Line 2625:
  
 === Пример на SHELL === === Пример на SHELL ===
 +
 +
  
 <​code>​ <​code>​
Line 2607: Line 2673:
 exten => 313,​n,​Hangup() exten => 313,​n,​Hangup()
 ... ...
 +</​code>​
 +
 +Решение от Кузьмина Алексея,​ скрипты взаимоисключающие,​ один только переводит полное ФИО в фамилию + инициалы,​ второй еще транслитирует
 +
 +<​code>​
 +Место хранения /​var/​lib/​asterisk/​agi-bin
 +
 +Сделать исполняемыми chmod +x
 +
 +exten => _X.,​1,​AGI(shortname.sh,​${CALLERID(name)},​${CALLERID(num)})
 +exten => _X.,​1,​AGI(translite.sh,​${CALLERID(name)},​${CALLERID(num)})
 +
 +shortname.sh
 +
 +#!/bin/bash
 +fio=""​
 +words=($1)
 +num=$2
 +m=${#​words[@]}
 +for ((i=0;​i<​=m-1;​i++));​ do
 +    word=${words[$i]}
 +    if [ $i -gt 0 ]; then
 +        word=${word:​0:​1}.
 +    fi
 +    if [ $i -eq 0 ]; then
 +        fio="​${word} "
 +    else
 +        fio="​${fio}${word}"​
 +    fi
 +done
 +echo "SET CALLERID \"​$fio\"<​$num>"​
 +
 +translite.sh
 +
 +#!/bin/bash
 +fio=""​
 +words=($1)
 +num=$2
 +m=${#​words[@]}
 +for ((i=0;​i<​=m-1;​i++));​ do
 +    word=${words[$i]}
 +    if [ $i -gt 0 ]; then
 +        word=${word:​0:​1}.
 +    fi
 +    str=`echo $word | sed "​y/​абвгдеёзийклмнопрстуфыэ/​abvgdeeziyklmnoprstufye/"​`
 +    str=`echo $str | sed "​y/​АБВГДЕЁЗИЙКЛМНОПРСТУФЫЭ/​ABVGDEEZIYKLMNOPRSTUFYE/"​`
 +    str=${str//​ж/​zh} str=${str//​Ж/​Zh};​
 +    str=${str//​х/​kh} str=${str//​Х/​Kh};​
 +    str=${str//​ц/​ts} str=${str//​Ц/​Ts};​
 +    str=${str//​ч/​ch} str=${str//​Ч/​Ch};​
 +    str=${str//​ш/​sh} str=${str//​Ш/​Sh};​
 +    str=${str//​щ/​sch} str=${str//​Щ/​Sch};​
 +    str=${str//​ъ/​} str=${str//​Ъ/​};​
 +    str=${str//​ь/​} str=${str//​Ь/​};​
 +    str=${str//​ю/​yu} str=${str//​Ю/​Yu};​
 +    str=${str//​я/​ya} str=${str//​Я/​Ya};​
 +    if [ $i -eq 0 ]; then
 +        fio="​${str} "
 +    else
 +        fio="​${fio}${str}"​
 +    fi
 +done
 +echo "SET CALLERID \"​$fio\"<​$num>"​
 </​code>​ </​code>​
  
Line 2640: Line 2769:
   * [[http://​www.jcgonzalez.com/​test-asterisk-ami-telnet|Log in, Log out from Asterisk AMI with Telnet]]   * [[http://​www.jcgonzalez.com/​test-asterisk-ami-telnet|Log in, Log out from Asterisk AMI with Telnet]]
   * [[http://​habrahabr.ru/​company/​centosadmin/​blog/​161521/​|Asterisk:​ обратный вызов с использованием AMI и PHP]]   * [[http://​habrahabr.ru/​company/​centosadmin/​blog/​161521/​|Asterisk:​ обратный вызов с использованием AMI и PHP]]
 +  * [[https://​habr.com/​ru/​articles/​264819/​|Asterisk Manager Interface в диалплане]]
 +  * [[https://​voxlink.ru/​kb/​book/​interfejs-upravlenija-asterisk-ami/​]]
   * Программирование диалогов expect [[Программирование диалогов expect#​Asterisk AMI]]   * Программирование диалогов expect [[Программирование диалогов expect#​Asterisk AMI]]
  
Line 2647: Line 2778:
 [general] [general]
 enabled = yes enabled = yes
 +;webenabled = yes
 port = 5038 port = 5038
 bindaddr = 127.0.0.1 bindaddr = 127.0.0.1
Line 2689: Line 2821:
  
  
-=== Настройка доступа ​к ARI ===+=== Настройка ​http доступа ===
 <​code>​ <​code>​
 # cat /​etc/​asterisk/​http.conf # cat /​etc/​asterisk/​http.conf
Line 2698: Line 2830:
 ;​bindaddr=0.0.0.0 ;​bindaddr=0.0.0.0
 bindport=8088 bindport=8088
-</​code><​code>​+</​code>​ 
 +=== Настройка доступа к ARI === 
 +<​code>​
 # cat /​etc/​asterisk/​ari.conf # cat /​etc/​asterisk/​ari.conf
 </​code><​code>​ </​code><​code>​
Line 2724: Line 2858:
   * [[https://​stackoverflow.com/​questions/​28064526/​how-to-get-all-dialer-events-from-asterisk-rest-api-ari|How to get all dialer events from Asterisk REST API (ARI)?]]   * [[https://​stackoverflow.com/​questions/​28064526/​how-to-get-all-dialer-events-from-asterisk-rest-api-ari|How to get all dialer events from Asterisk REST API (ARI)?]]
  
 +  * nodejs
 <​code>​ <​code>​
-debian9# curl -sL https://​deb.nodesource.com/​setup_9.x | sudo -E bash - 
- 
 # apt install -y nodejs npm # apt install -y nodejs npm
  
Line 2732: Line 2865:
  
 # wscat -c "​ws://​localhost:​8088/​ari/​events?​api_key=asterisk:​asterisk&​app=my-first-app" ​ # wscat -c "​ws://​localhost:​8088/​ari/​events?​api_key=asterisk:​asterisk&​app=my-first-app" ​
 +</​code>​
 +
 +  * python
 +<​code>​
 +# apt install python3-websocket
 +
 +# python3
 +</​code><​code>​
 +import websocket
 +def on_message(wsapp,​ message):
 +    print(message)
 +
 +wsapp = websocket.WebSocketApp("​ws://​localhost:​8088/​ari/​events?​api_key=asterisk:​asterisk&​app=my-first-app",​ on_message=on_message)
 +wsapp.run_forever()
 +
 +
 </​code><​code>​ </​code><​code>​
 *CLI> ari show apps *CLI> ari show apps
Line 3122: Line 3271:
 ==== Использование хешей паролей для каналов типа user ==== ==== Использование хешей паролей для каналов типа user ====
  
-[[http://​www.voip-info.org/​wiki/​view/​Asterisk+sip+md5secret]]+  * [[http://​www.voip-info.org/​wiki/​view/​Asterisk+sip+md5secret]] 
 +  * [[http://​asterisk-support.ru/​forum/​topics/​3032/​|SIP авторизация и MD5]]
  
 <​code>​ <​code>​
Line 3141: Line 3291:
 ==== Зашита от несанкционированного использования ==== ==== Зашита от несанкционированного использования ====
  
 +  * [[http://​voipapplication.blogspot.com/​2009/​01/​120000-phone-bill-voip-hacked-small.html|"​Voip hackers runs up a phone bill worth $120,​000"​.]]
 +
 +  * [[https://​habr.com/​ru/​companies/​myasterisk/​articles/​130325/​|9 правил,​ как защитить свой Asterisk!]]
   * [[http://​subnets.ru/​blog/?​p=1552|Защита Asterisk или несколько способов как защититься от подбора пароля к SIP аккаунту]]   * [[http://​subnets.ru/​blog/?​p=1552|Защита Asterisk или несколько способов как защититься от подбора пароля к SIP аккаунту]]
   * [[http://​tamkovich.com/​2009/​04/​asterisk-sip-security/​|Asterisk:​ SIP и безопасность]]   * [[http://​tamkovich.com/​2009/​04/​asterisk-sip-security/​|Asterisk:​ SIP и безопасность]]
-  * [[http://​voipapplication.blogspot.com/​2009/​01/​120000-phone-bill-voip-hacked-small.html|"​Voip hackers runs up a phone bill worth $120,​000"​.]]+
  
 ===== WebRTC ===== ===== WebRTC =====
Line 3230: Line 3383:
  
   * [[Голосовые сервисы помогут голосовой почте]]   * [[Голосовые сервисы помогут голосовой почте]]
 +
 +==== Сотрудник звонит на внешний номер, внешний номер перезванивает ====
 +<​code>​
 +Сотрудник звонит на внешний номер, номер не отвечает или занят.
 +
 +Внешний номер перезванивает на внешний номер организации (с которого у него пропущенный),​ где по умолчанию его должен встретить IVR.
 +
 +Если в течении последних Х минут в cdr есть запись звонка на этот внешний номер с состоянием номер не отвечает или занят, то соединить с внутренним номер с которого ему звонили.
 +
 +ДОП.: Если при этом в cdr есть запись что с этим внешним номером звонок состоялся(по времени после не отвеченного,​ направление не важно, внешний номер сам перезвонил и дозвонился или до него дозвонились со второго раза), то переключить на IVR.
 +
 + 
 +
 +Решение собственное,​ если есть что улучшить буду рад.
 +
 +Адаптировано под вашу методичку,​ но лучше проверить.
 +
 + 
 +
 +/​etc/​asterisk/​func_odbc.conf
 +
 + 
 +
 +[NOTANSWERED_BY_CALLERID]
 +
 +dsn=asterisk
 +
 +readsql=SELECT cnum FROM cdr WHERE dst='​${ARG1}'​ AND disposition<>'​ANSWERED'​ AND (calldate >= (SELECT COALESCE(MAX(calldate),​ now() - interval ${ARG2} minute) AS calldate FROM cdr WHERE (dst='​${ARG1}'​ OR src='​${ARG1}'​) AND disposition='​ANSWERED'​ AND (calldate >= now() - interval ${ARG2} minute) ORDER BY calldate DESC LIMIT 1)) ORDER BY calldate DESC LIMIT 1;
 +
 + 
 +
 +/​etc/​asterisk/​extensions.conf
 +
 + 
 +
 +exten => voip1_00000X,​1,​Set(NOTANSWERED=${ODBC_NOTANSWERED_BY_CALLERID(${CALLERID(num)},​5)}) ; External number, # minutes to search not answered call
 +
 +same => n,​GotoIf($[${LEN(${NOTANSWERED})} != 0]?recall)
 +
 +same => n,​Goto(ivr,​s,​1)
 +
 +same => n(recall),​Set(CALLERID(name)=RECALL ${CALLERID(name)})
 +
 +same => n,​Dial(PJSIP/​${NOTANSWERED},​60)
 +
 + 
 +
 +Вызывается функция ODBC с передачей ей номера звонящего и количества минут за которые искать записи.
 +
 +В SQL запросе вначале выполняется поиск за указанный интервал в минутах отвеченных звонков с участием внешнего номера и возвращается дата самого последнего звонка,​ если он есть, либо дата начала указанного интервала поиска (now() – 5 минут, например) и после этого выполняется поиск не отвеченных звонков на указанный внешний номер за указанный интервал.
 +
 +После этого к CALLERID(name) звонящего добавляется RECALL, чтобы уведомить сотрудника,​ что ему перезванивают,​ и осуществляется соединение с номером сотрудника от которого был последний не отвеченный звонок,​ или переключение на IVR, если не отвеченных звонков не было.
 +
 + 
 +
 +Алексей Михайлович Кузьмин
 +</​code>​
 ==== Принудительный провижининг ==== ==== Принудительный провижининг ====
 <​code>​ <​code>​
сервис_asterisk.1650211307.txt.gz · Last modified: 2022/04/17 19:01 by val