This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
сервис_asterisk [2022/08/26 18:06] val [Парковка разговора] |
сервис_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 853: | Line 934: | ||
| 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"; | 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 1487: | 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 1498: | 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 1607: | Line 1612: | ||
| [general] | [general] | ||
| ... | ... | ||
| - | ;featuredigittimeout = 1000 | + | featuredigittimeout = 3000 |
| ... | ... | ||
| [featuremap] | [featuremap] | ||
| Line 1793: | 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 1816: | 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 1838: | 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 1921: | 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 1939: | 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 1950: | 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 2041: | 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 2102: | 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 2111: | 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 2120: | Line 2153: | ||
| ... | ... | ||
| automon => *11 | automon => *11 | ||
| + | ... | ||
| + | ;automixmon => *3 | ||
| ... | ... | ||
| </code><code> | </code><code> | ||
| Line 2127: | 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 2186: | 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 2216: | 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 2257: | 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 2269: | 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 2419: | 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 2438: | Line 2493: | ||
| ;timeout=10 | ;timeout=10 | ||
| - | ;для демонстрации на многоканальном телефоне установить call-limit=1 | + | ;member => SIP/403 |
| - | ;member => SIP/403 ; (можно занять звонком на 311) | + | |
| ;member => SIP/user1@mailcgp | ;member => SIP/user1@mailcgp | ||
| Line 2539: | 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 2571: | Line 2625: | ||
| === Пример на SHELL === | === Пример на SHELL === | ||
| + | |||
| + | |||
| <code> | <code> | ||
| Line 2617: | 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 2650: | 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 2657: | 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 2699: | Line 2821: | ||
| - | === Настройка доступа к ARI === | + | === Настройка http доступа === |
| <code> | <code> | ||
| # cat /etc/asterisk/http.conf | # cat /etc/asterisk/http.conf | ||
| Line 2708: | 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 2734: | 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 2742: | 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 3132: | 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 3151: | 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 3240: | 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> | ||