
IP ATC Asterisk este un instrument puternic în domeniul IP-telefoniei. Interfața web FreePBX, creată pentru Asterisk, simplifică semnificativ configurarea și reduce pragul de intrare în sistem.
Dacă poți imagina o sarcină legată de IP-telefonie, este aproape sigur că aceasta poate fi realizată în Asterisk. Dar asigură-te că va fi nevoie de perseverență și răbdare din partea ta.
Am avut sarcina de a configura notificări prin e-mail pentru apelurile ratate. Mai exact, de a informa prin e-mail în cazurile în care un apel primit a fost transferat în coadă, dar nimeni (dintre agenți) nu a răspuns la acest apel.
Surprinzător, nu am găsit soluții standard pentru această sarcină în FreePBX. Cum am rezolvat această problemă, voi relata mai departe.
Prefață
Înainte de a aborda problema «direct», am căutat desigur informații pe internet, dar nu am găsit soluții complete (poate că am căutat slab, dar ce să fac...).
Nu sunt atât de multe cunoștințe despre lucrul direct în Asterisk pe cât ne-am dori, așa că soluția propusă , nu a fost complet gândită și a fost abandonată.
Ne-a plăcut soluția propusă de , chiar dacă nu a funcționat. Din acest motiv, s-a subliniat că lucrul în Asterisk trebuie făcut în contextul cozilor [ext-queues]. Și având în vedere că lucrăm în FreePBX, este necesar să lucrăm în fișierul de configurare «extensions_override_freepbx.conf». Am observat că este convenabil să «prindem apelurile ratate» înainte de evenimentul hangupcall (încetarea apelului).
Citind discuția , mi-a venit ideea că trebuie să filtrăm în CDR variabila «Disposition» pentru toți agenții din coadă. Și după ce am citit informațiile, s-au format pașii foarte concreți pentru rezolvarea problemei stabilite.
Ce avem:
Există FreePBX 13.0.197, care folosește Asterisk 13.12.1. Versiunea OS SHMZ release 6.6 (Final). Distribuția se bazează pe CentOS.
În Asterisk este configurat un IVR (meniul vocal) care distribuie apelurile primite în diferite cozi. Fiecărei cozi îi sunt asignați agenți, adică operatori.
Teorie
Ce se întâmplă în Asterisk
Când un apel primit ajunge la Asterisk, acesta este direcționat către IVR. Caller-ul face o alegere apăsând un anumit număr pe telefon și ajunge într-o anumită coadă. După aceea, toate agenții liberi din coadă primesc simultan apelul.
Pentru a înțelege mai bine ce se întâmplă în acest moment și ce se întâmplă mai departe, să ne referim la Report CDR (Fig. 1).

Fig. 1
Când un apel intrat a fost plasat în așteptare, valoarea variabilei „Disposition” a devenit „NO ANSWER” pentru toți agenții care nu erau ocupați în acel moment. Variabila „Disposition” putea avea și alte valori (vezi. ), cu excepția valorii „ANSWERED”. Iar în momentul în care unul dintre agenți răspunde la apelul intrat, valoarea variabilei „Disposition” a acestui agent devine „ANSWERED”.
Din Raportul CDR se poate observa că atunci când apelul a trecut în așteptare (în coloana App, valoarea devine „Queue”), toate evenimentele apar cu același „uniqueid” (coloana System).
Pe scurt despre CDR
Este important să înțelegem ce este CDR și în ce moment sunt înregistrate datele pe care le observăm în Raportul CDR. CDR, în raport cu sistemul de operare, este o bază de date în care Asterisk înregistrează un raport detaliat de apeluri (vezi. ). În cazul nostru, este vorba despre baza numită asteriskcdrdb, care se află în mysql. Prin experiență, am constatat că datele unui apel cu un anumit „uniqueid” sunt introduse în asteriskcdrdb nu imediat după ce are loc un eveniment, ci după evenimentul hangupcall (finalizarea apelului).
Principiul de funcționare al soluției create
Dat fiind că avem mai multe cunoștințe în bash decât în Asterisk, ideea principală a fost următoarea. Înainte de evenimentul hangupcall, apelați un script bash. În acest script, transmiteți 3 parametri. Primul parametru este „uniqueid”, pentru a filtra datele obținute din CDR. Al doilea parametru este „CALLERID(num)” (numărul apelantului), pentru a ști cui să sunăm înapoi. Al treilea parametru este „NODEST” (numărul cozii), în care a intrat apelul, pentru a ști despre ce problemă a fost apelul și cui să trimitem notificarea prin e-mail despre apelul ratat.
Scriptul bash trebuie să se conecteze la baza asteriskcdrdb în mysql și să preia toate valorile variabilei „Disposition” cu un anumit „uniqueid”. Din datele obținute, trebuie excluse valorile: „NO ANSWER”, „BUSY”, „FAILED”, „UNKNOWN”. Ca rezultat, vor rămâne fie „ANSWERED” — apelul intrat a fost răspuns, fie fără nimic — apel ratat.
Mai departe, dacă apelul a fost ratat, scriptul trebuie să trimită o notificare prin e-mail.
Înaintându-mă, vreau să subliniez un aspect important. Asterisk execută comenzile în mod secvențial, așteptându-le finalizarea (ceea ce este, de fapt, logic). Vom apela scriptul bash înainte de a se executa comanda hangupcall. Astfel, în momentul execuției efective a scriptului, informația despre „uniqueid” căutată nu va fi încă înregistrată în CDR. Pentru a rezolva această problemă, vom apela scriptul bash cu parametrul „&”, astfel încât Asterisk să treacă imediat la următorul pas, adică hangupcall. Iar în interiorul scriptului bash, la început, vom seta o mică întârziere în timp, pentru a da timp Asterisk-ului să înregistreze datele cu „uniqueid”-ul care ne interesează în CDR.
Practică
Înainte de a trece la configurarea Asterisk și de a crea scriptul bash, trebuie să configurăm trimiterea de notificări prin e-mail. Pentru aceasta, vom folosi utilitarul postfix.
Configurarea postfix
Avem un domeniu de poștă „lucky.ru”, găzduit la Yandex. Vom configura postfix în modul de client smtp și vom trimite emailuri de la contul asterisk@lucky.ru.
Decizia a fost preluată de aici: .
În primul rând, vom instala/update verifica existența pachetelor:
yum install postfix
yum install mailx
yum install cyrus-sasl cyrus-sasl-lib cyrus-sasl-plainNu vom suprascrie fișierul principal de configurare postfix „/etc/postfix/main.cf”, ci vom crea o copie de rezervă:
cp /etc/postfix/main.cf /etc/postfix/main.cf.savVom edita fișierul „/etc/postfix/main.cf” și îl vom aduce la următoarea formă:
nano /etc/postfix/main.cf
#####################
relayhost =
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/private/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_type = cyrus
smtp_sasl_mechanism_filter = login
smtp_sender_dependent_authentication = yes
sender_dependent_relayhost_maps = hash:/etc/postfix/private/sender_relay
smtp_generic_maps = hash:/etc/postfix/generic
smtp_tls_CAfile = /etc/postfix/ca.pem
smtp_use_tls = yes
smtputf8_autodetect_classes = all
#####################Nu fiecare linie din „/etc/postfix/main.cf” poate fi comentată. Comentariile din unele linii nu sunt recunoscute de parser și sunt transmise pentru procesare, ceea ce duce la erori. Este mai bine să renunțăm la comentarii în interiorul acestui fișier. Puteți experimenta cu aceasta, rulând în fereastra alăturată „tail -f /var/log/messages”.
Vreau să subliniez linia „smtputf8_autodetect_classes = all”. Această înregistrare activează utf-8 implicit, ceea ce permite utilizarea chirilicei atât în corpul emailului, cât și în subiectul emailului fără manipulări suplimentare (Vezi. ).
Vom crea un director pentru fișierele de configurare:
mkdir /etc/postfix/privateEdităm fișierul "/etc/postfix/private/sender_relay". Aici trebuie să specificăm la ce server smtp trebuie să facem referire atunci când folosim domeniul nostru de email:
nano /etc/postfix/private/sender_relay
#####################
@lucky.ru smtp.yandex.ru
#####################Edităm fișierul "/etc/postfix/private/sasl_passwd". Aici vom specifica adresa de e-mail pe care o vom folosi pentru a trimite mesaje, precum și numele de utilizator și parola pentru acest cont (numele de utilizator și parola se specifică prin două puncte):
nano /etc/postfix/private/sasl_passwd
#####################
asterisk@lucky.ru asterisk@lucky.ru:password_asterisk
#####################Edităm fișierul "/etc/postfix/generic". Aici vom scrie regulile de substituție pentru adresa de email de expediere (vezi. ):
nano /etc/postfix/generic
#####################
root asterisk@lucky.ru
root@localhost asterisk@lucky.ru
root@localhost.localdomain asterisk@lucky.ru
root@freepbx asterisk@lucky.ru
root@freepbx.localdomain asterisk@lucky.ru
root@asterisk asterisk@lucky.ru
root@asterisk.localdomain asterisk@lucky.ru
asterisk asterisk@lucky.ru
asterisk@localhost asterisk@lucky.ru
asterisk@localhost.localdomain asterisk@lucky.ru
asterisk@freepbx asterisk@lucky.ru
asterisk@freepbx.localdomain asterisk@lucky.ru
asterisk@asterisk asterisk@lucky.ru
asterisk@asterisk.localdomain asterisk@lucky.ru
root@localdomain.localdomain asterisk@lucky.ru
#####################Adresa de expediere inițială depinde de conținutul " /etc/hosts" și " /etc/hostname", precum și de numele de utilizator care va trimite mesajul. Cu alte cuvinte, deși folosim un client smtp și trimitem mesaje din asterisk@lucky.ru, postfix va înlocui inițial adresa expeditorului cu „ceva propriu”, iar acest lucru trebuie corectat prin regulile din acest fișier de configurare.
Iată conținutul fișierului meu "/etc/hosts":
cat /etc/hosts
#####################
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 asterisk.localdomain
127.0.0.1 localhost.localdomain localhost
::1 asterisk localhost localhost6
#####################Este important ca serverul să aibă un domeniu (valoarea după punct), deoarece utilitarul mail "caută" numele domeniului în "/etc/hosts" și, dacă "nu îl găsește" imediat, va continua să facă acest lucru timp de câteva minute și abia apoi va trimite mesajul. Cu alte cuvinte, dacă domeniul nu este specificat, mesajul va fi trimis cu o întârziere de câteva minute.
Iată conținutul fișierului meu "/etc/hostname":
cat /etc/hostname
#####################
asterisk
#####################Apoi, este necesar să convertim fișierele de configurare create în baze de date indexate, pentru aceasta vom rula următoarea comandă:
postmap /etc/postfix/generic && postmap /etc/postfix/private/{sasl_passwd,sender_relay}Apoi, trebuie să descărcăm și să plasăm pe server certificatul smtp.yandex.ru, pentru aceasta vom rula următoarea comandă:
openssl s_client -starttls smtp -crlf -connect smtp.yandex.ru:25 > /etc/postfix/ca.pemDar după ce informațiile tehnice vor apărea pe ecran, echipa va „continua să rămână”. Apăsați Ctrl+C pentru a o întrerupe.
Acum, să eliminăm manual toată mizeria din fișierul obținut și să păstrăm doar certificatul. Ar trebui să arate asemănător cu acesta:
nano /etc/postfix/ca.pem
#####################
-----BEGIN CERTIFICATE-----
MIIGazCCBVOgAwIBAgIQcUU9mJXW4OUs5Gf0JfLtsjANBgkqhkiG9w0BAQsFADBf
...
nRG0DfdqYIuPGApFORYe
-----END CERTIFICATE-----
#####################Și, în cele din urmă, să repornim postfix:
service postfix restartTrimiți un e-mail de test:
echo "Acesta este corpul e-mailului" | mail -s "Aceasta este subiectul" admin@lucky.roadmin@lucky.ro — adresa de destinație
Aceasta este configurația finalizată pentru postfix.
Scriem un script bash
Creăm un director pentru stocarea scriptului bash (aici unde preferă fiecare):
mkdir /home/asterisk/scriptsCreăm fișierul scriptului bash:
touch /home/asterisk/scripts/noanswer.shAcordăm fișierului script drepturi de execuție:
chmod +x /home/asterisk/scripts/noanswer.shDacă aveți dubii cu privire la drepturile fișierului, pentru perioada de depanare puteți oferi acces total la fișier. Dar acest lucru este „nesigur”.
chmod 777 /home/asterisk/scripts/noanswer.shTextul scriptului bash:
nano /home/asterisk/scripts/noanswer.sh
#####################
#! /bin/bash
sleep 7
res_sql="SELECT disposition FROM cdr WHERE uniqueid = '$1'"
answer=`mysql -u freepbxuser -pPassword_freepbxuser -D asteriskcdrdb -B -N -e "$res_sql" | grep -E -v "NO ANSWER|BUSY|FAILED|UNKNOWN" | head -n 1`
error_kod=0
if [ "$answer" != "ANSWERED" ]
then
case $3 in
68800)
address="big_boss@lucky.ro"
subject="pe o problemă importantă"
;;
63100)
address="debian@lucky.ro"
subject="pe probleme legate de linux debian"
;;
63200)
address="windows@lucky.ro"
subject="pe probleme legate de windows"
;;
63300)
address="freebsd@lucky.ro"
subject="pe probleme legate de freebsd"
;;
63400)
address="ubuntu@lucky.ro"
subject="pe probleme legate de linux ubuntu"
;;
63500)
address="centos@lucky.ro"
subject="pe probleme legate de linux centos"
;;
*)
address="admin@lucky.ro"
error_kod=1
;;
esac
case $error_kod in
0)
echo "Apel ratat de la abonatul $2, care a sunat $subject." | mail -s "Apel ratat de la $2" $address
echo "Apel ratat pentru $address de la abonatul $2, care a sunat $subject. uid=$1" | mail -s "Apel ratat de la $2" admin@lucky.ro
;;
1)
echo "Apel ratat de la $2. Coada este necunoscută. uid=$1" | mail -s "Apel ratat de la $2" admin@lucky.ro
;;
esac
fi
#####################Analiză scurtă a scriptului:
„sleep 7”:
Aceasta este întârzierea de timp de care vorbeam mai devreme. Am stabilit o întârziere de 7 secunde. Deși cred că o secundă ar fi suficient.
„res_sql="SELECT disposition FROM cdr WHERE uniqueid = '$1'"”:Am mutat interogarea în mysql într-o variabilă separată pentru comoditate.
În continuare, facem o interogare în MySQL și filtrăm rezultatul obținut. Eliminăm toate opțiunile în afară de „ANSWERED”, dacă există. Dacă sunt mai multe valori „ANSWERED”, trebuie să păstrăm doar una. La final, în variabila „answer” vom obține fie „ANSWERED”, fie „”.
Dacă valoarea variabilei „answer” nu este egală cu „ANSWERED”, atunci acesta este un apel ratat. În funcție de numărul din coadă, folosind operatorul case, vom stabili adresa cui trebuie să trimitem notificarea prin e-mail și ce să scriem în acest mesaj (partea modificabilă a mesajului).
În continuare, vom analiza cazul în care coada este definită în Asterisk, dar nu este descrisă în script. În acest caz, admin@lucky.ru va primi un e-mail, indicând că coada nu este cunoscută scriptului.
Dacă coada este descrisă, atunci un mesaj va fi trimis la destinație și un mesaj duplicat va fi trimis la admin@lucky.ru cu menționarea „uniqueid”, pentru a putea urmări evenimentele legate de acest apel, dacă este necesar.
Aceasta este ultima parte a scriptului.
Vreau să subliniez că pentru a ne conecta la MySQL am folosit un nume de utilizator și o parolă, pe care le-am aflat anterior. În FreePBX, pentru a afla numele de utilizator Asterisk în MySQL, executați următoarea comandă:
cat /etc/amportal.conf | grep AMPDBUSERȘi pentru a afla parola utilizatorului Asterisk în MySQL, executați următoarea comandă:
cat /etc/amportal.conf | grep AMPDBPASSConfigurarea Asterisk
Folosim FreePBX. În FreePBX există diferite tipuri de fișiere de configurare (vezi. ), unele dintre ele sunt rescrise de FreePBX la repornire, iar altele nu sunt rescrise (se numesc custom), deoarece sunt special concepute pentru utilizator.
Vom lucra cu fișierul de configurare „extensions_override_freepbx.conf”, deoarece acesta aparține tipului custom.
Pentru început, să ne asigurăm că fișierul „/etc/asterisk/extensions.conf” include fișierul „extensions_override_freepbx.conf”. Pentru a face acest lucru, executați următoarea comandă:
cat /etc/asterisk/extensions.conf | grep extensions_override_freepbx.conf
#####################
#include extensions_override_freepbx.conf
#####################Editați fișierul „/etc/asterisk/extensions_override_freepbx.conf” și aduceți-l la următoarea formă:
nano /etc/asterisk/extensions_override_freepbx.conf
#####################
[ext-queues]
exten => h,1,System(/home/asterisk/scripts/noanswer.sh ${CDR(uniqueid)} ${CALLERID(num)} ${NODEST} &)
exten => h,2,Macro(hangupcall,)
#####################Așa cum am scris anterior, simbolul „&” la sfârșit este obligatoriu. Deoarece vom lucra în scriptul bash cu date CDR direct din baza de date mysql, iar aceste date sunt introduse în mysql doar după executarea „exten => h,2,Macro(hangupcall,)”, este necesar să nu așteptăm finalizarea execuției scriptului bash, ci să trecem la următorul pas în Asterisk. Iar scriptul bash ar trebui să conțină o întârziere în timp, înainte de a executa partea sa principală.
Pentru ca modificările din fișierul de configurare „/etc/asterisk/extensions_override_freepbx.conf” să aibă efect, este necesară repornirea nucleului Asterisk cu următoarea comandă:
/usr/sbin/asterisk -rx "core restart now"Acest lucru trebuie făcut după ce scriptul bash a fost creat.
Concluzie
Probabil, acesta este modul 1001 de „a prinde apelurile ratate” în Asterisk. Împărtășiți în comentarii cum rezolvați această problemă. Și ce, în opinia dumneavoastră, ar putea fi îmbunătățit/modificat/optimizat. Vom fi recunoscători pentru ideile constructive.
Sursa: habr.com
