
IP ATC Asterisk è una potente soluzione nel campo della telefonia IP. L'interfaccia web FreePBX, progettata per Asterisk, semplifica notevolmente la configurazione e riduce la barriera all'ingresso nel sistema.
Se riesci a concepire qualsiasi compito legato alla telefonia IP, è quasi certamente realizzabile in Asterisk. Ma sii certo che ti serviranno perseveranza e pazienza.
Abbiamo avuto l'incarico di configurare le notifiche via e-mail per le chiamate perse. In particolare, informare via e-mail nei casi in cui una chiamata in arrivo è stata messa in attesa, ma nessuno (tra gli agenti) ha risposto a questa chiamata in arrivo.
Sorprendentemente, non abbiamo trovato strumenti predefiniti per risolvere questo problema in FreePBX. Spiegherò come abbiamo affrontato questa situazione nel seguito.
Prefazione
Prima di affrontare il problema 'direttamente', abbiamo cercato informazioni su internet, ma non abbiamo trovato soluzioni pronte (forse abbiamo cercato male, ma che ci possiamo fare...).
Le competenze dirette in Asterisk non sono così numerose come si vorrebbe, quindi la soluzione proposta , non è stata pienamente elaborata ed è stata scartata.
Ci è piaciuta la soluzione proposta , anche se non ha funzionato. Da qui è emerso che è necessario lavorare in Asterisk nel contesto delle code [ext-queues]. E poiché lavoriamo in FreePBX, è necessario operare nel file di configurazione "extensions_override_freepbx.conf". Abbiamo notato che è comodo "catturare le chiamate perse" prima dell'evento hangupcall (fine della chiamata).
Leggendo la discussione , è emersa l'idea di filtrare nella variabile CDR "Disposition" per tutti gli agenti nella coda. E dopo aver letto le informazioni si sono formate passi molto concreti per risolvere il problema posto.
Cosa abbiamo:
Abbiamo FreePBX 13.0.197, che utilizza Asterisk 13.12.1. Versione del SO SHMZ release 6.6 (Final). La distribuzione è basata su CentOS.
In Asterisk è configurato un IVR (menu vocale) che distribuisce le chiamate in ingresso su diverse Queue (code). A ciascuna coda sono assegnati Agents (agenti), cioè operatori.
Teoria
Cosa succede in Asterisk
Quando una chiamata in ingresso arriva su Asterisk, questa viene inviata all'IVR. Il chiamante fa una scelta premendo un determinato numero sul telefono, e finisce in una coda specifica. Dopo di che, a tutti gli agenti liberi della coda arriva simultaneamente la chiamata.
Per comprendere meglio cosa stia accadendo in questo momento e cosa succederà dopo, facciamo riferimento al Report CDR (Fig.1).

Fig.1
Quando una chiamata in arrivo entra in coda, il valore della variabile «Disposition» diventa «NO ANSWER» per tutti gli agenti, a meno che non siano occupati in quel momento. La variabile «Disposition» può assumere anche altri valori (cfr. ), oltre a «ANSWERED». Nel momento in cui uno degli agenti risponde alla chiamata in arrivo, il valore della variabile «Disposition» per quell'agente diventa «ANSWERED».
Dal Report CDR si può notare che quando la chiamata è passata in coda (nella colonna App il valore diventa «Queue»), tutti gli eventi presentano lo stesso «uniqueid» (colonna System).
Breve introduzione al CDR
È importante comprendere cos'è il CDR e in quale momento vengono registrati i dati che osserviamo nel Report CDR. Il CDR, rispetto al sistema operativo, è un database in cui Asterisk registra un report dettagliato delle chiamate (cfr. ). In questo caso, si tratta di un database chiamato asteriskcdrdb, che si trova in mysql. Abbiamo scoperto che i dati sulle chiamate con un determinato «uniqueid» vengono inseriti in asteriskcdrdb non subito dopo il verificarsi di un evento, ma dopo l'evento hangupcall (fine della chiamata).
Il principio di funzionamento della soluzione creata
Poiché abbiamo più conoscenze in bash che in Asterisk, l'idea principale è stata la seguente. Prima dell'evento hangupcall, chiamare uno script bash. In questo script, passare 3 parametri. Il primo parametro è «uniqueid», per filtrare i dati ottenuti da CDR. Il secondo parametro è «CALLERID(num)» (numero del chiamante), per sapere a chi richiamare. Il terzo parametro è «NODEST» (numero della coda), nel quale è arrivata la chiamata, per sapere per quale motivo è stata effettuata la chiamata e a chi inviare l'e-mail di notifica della chiamata persa.
Lo script bash deve connettersi al database asteriskcdrdb in mysql e ottenere tutti i valori della variabile «Disposition» con un determinato «uniqueid». Dovrebbero essere escluse le seguenti voci: «NO ANSWER», «BUSY», «FAILED», «UNKNOWN». Ne risulterà solo «ANSWERED» — se la chiamata in entrata è stata risposta, oppure nessun dato — se la chiamata è stata persa.
Inoltre, se la chiamata è stata persa, lo script deve inviare una notifica via e-mail.
Anticipando un punto importante, Asterisk esegue i comandi in modo sequenziale, attendendo il loro completamento (il che è logico). E chiameremo lo script bash prima che venga eseguito il comando hangupcall. Pertanto, nel momento in cui lo script viene eseguito, nel CDR non ci sarà ancora alcuna informazione sul «uniqueid» ricercato. Per risolvere questo problema, chiameremo lo script bash con il parametro «&», in modo che Asterisk passi immediatamente all'esecuzione del passaggio successivo, ovvero hangupcall. All'inizio dello script bash, imposteremo un piccolo ritardo per dare a Asterisk il tempo di inserire i dati del «uniqueid» che ci interessa nel CDR.
Pratica
Prima di passare alla configurazione di Asterisk e alla creazione dello script bash, è necessario impostare l'invio delle notifiche via e-mail. Per questo utilizzeremo l'utilità postfix.
Configurazione di postfix
Abbiamo un dominio email «lucky.ru», ospitato su Yandex. Configureremo postfix in modalità smtp-client e invieremo email dall'account asterisk@lucky.ru.
La soluzione è stata presa da qui: .
Per prima cosa installiamo/aggiorniamo/verifichiamo la presenza dei pacchetti:
yum install postfix
yum install mailx
yum install cyrus-sasl cyrus-sasl-lib cyrus-sasl-plainNon modificheremo il file di configurazione principale di postfix «/etc/postfix/main.cf», ma creeremo un backup:
cp /etc/postfix/main.cf /etc/postfix/main.cf.savModifichiamo il file «/etc/postfix/main.cf» portandolo alla seguente configurazione:
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
#####################Non si può commentare ogni riga in «/etc/postfix/main.cf». I commenti in alcune righe non sono riconosciuti dal parser e vengono elaborati, causando errori. È meglio evitare commenti all'interno di questo file. Puoi provare a verificarlo eseguendo in una finestra accanto «tail -f /var/log/messages».
Segnalo la riga «smtputf8_autodetect_classes = all». Questa impostazione abilita utf-8 di default, permettendo di utilizzare il carattere cirillico sia nel corpo dell'email che nell'oggetto senza ulteriori manovre (Vedi. ).
Creeremo una directory per i file di configurazione:
mkdir /etc/postfix/privateStiamo modificando il file «/etc/postfix/private/sender_relay». Qui dobbiamo specificare a quale server SMTP fare riferimento quando utilizziamo il nostro dominio email:
nano /etc/postfix/private/sender_relay
#####################
@lucky.ru smtp.yandex.ru
#####################Stiamo modificando il file «/etc/postfix/private/sasl_passwd». Qui indicheremo l'indirizzo email che utilizzeremo per inviare messaggi, insieme al nome utente e alla password di questo account (nome utente e password sono separati da due punti):
nano /etc/postfix/private/sasl_passwd
#####################
asterisk@lucky.ru asterisk@lucky.ru:password_asterisk
#####################Stiamo modificando il file «/etc/postfix/generic». Qui scriveremo le regole per la sostituzione dell'indirizzo in uscita (vedi. ):
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
#####################L'indirizzo IP di invio originale dipende dai contenuti di «/etc/hosts» e «/etc/hostname», nonché dal nome utente che invierà l'email. Cioè, nonostante utilizziamo un client SMTP e inviamo email da asterisk@lucky.ru, Postfix inizialmente inserisce comunque «qualcosa di suo» nell'indirizzo del mittente e questo deve essere corretto con le regole di questo file di configurazione.
Ecco il contenuto del mio file «/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
#####################È importante che il server abbia un dominio (valore dopo il punto), perché l'utilità mail «cerca» il nome del dominio in «/etc/hosts» e se non lo trova subito, continuerà a cercarlo per alcuni minuti e solo dopo invierà l'email. Cioè, se il dominio non è impostato, l'email verrà inviata con un ritardo di diversi minuti.
Ecco il contenuto del mio file «/etc/hostname»:
cat /etc/hostname
#####################
asterisk
#####################Poi è necessario convertire i file di configurazione creati in database indicizzati, per fare ciò eseguiamo il seguente comando:
postmap /etc/postfix/generic && postmap /etc/postfix/private/{sasl_passwd,sender_relay}Successivamente, dobbiamo scaricare e posizionare sul server il certificato smtp.yandex.ru, per fare ciò eseguiamo il seguente comando:
openssl s_client -starttls smtp -crlf -connect smtp.yandex.ru:25 > /etc/postfix/ca.pemMa dopo che le informazioni tecniche appariranno sullo schermo, il comando continuerà a 'rimanere in attesa'. Premi Ctrl+C per interromperlo.
Ora rimuoviamo manualmente tutto il superfluo dal file risultante e lasciamo solo il certificato. Dovrebbe risultare qualcosa di simile:
nano /etc/postfix/ca.pem
#####################
-----BEGIN CERTIFICATE-----
MIIGazCCBVOgAwIBAgIQcUU9mJXW4OUs5Gf0JfLtsjANBgkqhkiG9w0BAQsFADBf
...
nRG0DfdqYIuPGApFORYe
-----END CERTIFICATE-----
#####################E infine riavviamo postfix:
service postfix restartInvia una email di test:
echo "Questo è il corpo della email" | mail -s "Questo è l'oggetto" admin@lucky.ruadmin@lucky.ru — indirizzo di destinazione
Con questo, la configurazione di postfix è completata.
Scriviamo uno script bash
Creiamo una directory per memorizzare lo script bash (scegliete dove preferite):
mkdir /home/asterisk/scriptsCreiamo il file dello script bash:
touch /home/asterisk/scripts/noanswer.shConcediamo al file dello script i diritti di esecuzione:
chmod +x /home/asterisk/scripts/noanswer.shSe ci sono dubbi sui diritti del file, si può dare accesso completo al file temporaneamente per il debug. Ma questo "non è sicuro".
chmod 777 /home/asterisk/scripts/noanswer.shTesto dello script 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.ru"
subject="su una questione importante"
;;
63100)
address="debian@lucky.ru"
subject="per questioni linux debian"
;;
63200)
address="windows@lucky.ru"
subject="per questioni windows"
;;
63300)
address="freebsd@lucky.ru"
subject="per questioni freebsd"
;;
63400)
address="ubuntu@lucky.ru"
subject="per questioni linux ubuntu"
;;
63500)
address="centos@lucky.ru"
subject="per questioni linux centos"
;;
*)
address="admin@lucky.ru"
error_kod=1
;;
esac
case $error_kod in
0)
echo "Chiamata persa dall'utente $2, che ha chiamato $subject." | mail -s "Chiamata persa da $2" $address
echo "Chiamata persa per $address dall'utente $2, che ha chiamato $subject. uid=$1" | mail -s "Chiamata persa da $2" admin@lucky.ru
;;
1)
echo "Chiamata persa da $2. Coda sconosciuta. uid=$1" | mail -s "Chiamata persa da $2" admin@lucky.ru
;;
esac
fi
#####################Breve spiegazione dello script:
«sleep 7»:
È il ritardo di tempo di cui parlavo in precedenza. Abbiamo impostato un ritardo di 7 secondi. Anche se, penso, che un secondo sia più che sufficiente.
«res_sql="SELECT disposition FROM cdr WHERE uniqueid = '$1'"»:La richiesta in mysql è stata estratta in una variabile separata per comodità.
Successivamente, effettuiamo una richiesta in mysql e filtriamo l'output ricevuto. Rimuoviamo tutte le opzioni tranne "ANSWERED", se ce n'è una. Se ci sono più valori "ANSWERED", ne dobbiamo mantenere solo uno. Alla fine, ci ritroveremo con "answer" che conterrà o "ANSWERED" o "".
Se il valore della variabile "answer" non è uguale a "ANSWERED", significa che è stata una chiamata persa. A seconda del numero della coda, utilizzando l'operatore case, stabiliremo a chi deve essere inviata la notifica via e-mail e cosa scrivere in questo messaggio (parte modificabile del messaggio).
Successivamente, analizziamo il caso in cui la coda sia definita in Asterisk, ma non descritta nello script. In questo caso, admin@lucky.ru riceverà un'e-mail informandolo che la coda non è nota allo script.
Se la coda è definita, verrà inviato un messaggio all'indirizzo corretto e un'email duplicata a admin@lucky.ru con l'indicazione di "uniqueid", in modo che si possano monitorare gli eventi relativi a questa chiamata, se necessario.
Lo script si conclude qui.
Segnalo che per connettersi a mysql abbiamo utilizzato un nome utente e una password che abbiamo scoperto in anticipo. In FreePBX, per scoprire il nome utente di Asterisk in mysql, esegui il seguente comando:
cat /etc/amportal.conf | grep AMPDBUSERE per scoprire la password dell'utente Asterisk in mysql, esegui il seguente comando:
cat /etc/amportal.conf | grep AMPDBPASSConfigurazione di Asterisk
Utilizziamo FreePBX. In FreePBX ci sono diversi tipi di file di configurazione (vedi ), alcuni di essi vengono sovrascritti da FreePBX al riavvio, mentre altri non vengono sovrascritti (questi sono chiamati custom), poiché sono specificamente destinati all'utente.
Lavoreremo con il file di configurazione «extensions_override_freepbx.conf», poiché appartiene al tipo custom.
Per prima cosa, verifichiamo che il file «/etc/asterisk/extensions.conf» includa il file «extensions_override_freepbx.conf». Per farlo, eseguiamo il seguente comando:
cat /etc/asterisk/extensions.conf | grep extensions_override_freepbx.conf
#####################
#include extensions_override_freepbx.conf
#####################Modifichiamo il file «/etc/asterisk/extensions_override_freepbx.conf» e portiamolo alla seguente configurazione:
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,)
#####################Come ho già scritto, il simbolo «&» alla fine è obbligatorio. Poiché lavoreremo con dati CDR in uno script bash direttamente dal database MySQL, e questi dati vengono inseriti in MySQL solo dopo l'esecuzione di «exten => h,2,Macro(hangupcall,)», è necessario non attendere il completamento dello script bash, ma procedere all'esecuzione del passo successivo in Asterisk. Lo script bash stesso deve contenere un ritardo temporale prima di eseguire la propria parte principale.
Per fare in modo che le modifiche al file di configurazione «/etc/asterisk/extensions_override_freepbx.conf» abbiano effetto, è necessario riavviare il kernel di Asterisk con il seguente comando:
/usr/sbin/asterisk -rx "core restart now"Questo deve essere fatto dopo che lo script bash è stato creato.
Conclusione
Probabilmente questo è il 1001° modo per «catturare le chiamate perse» in Asterisk. Condividete nei commenti come affrontate voi questo compito. E cosa, secondo voi, può essere migliorato/rifatto/ottimizzato. Saremo grati per idee costruttive.
Fonte: habr.com
