
IP ATC Asterisk is een krachtige tool op het gebied van IP-telefonie. De webinterface FreePBX, ontworpen voor Asterisk, vereenvoudigt de configuratie aanzienlijk en verlaagt de drempel om het systeem in te voeren.
Als je een of andere taak kunt bedenken die verband houdt met IP-telefonie, is de kans groot dat deze kan worden gerealiseerd in Asterisk. Maar wees ervan verzekerd dat je vastberadenheid en geduld vereist zijn.
We stonden voor de taak om e-mailmeldingen over gemiste oproepen in te stellen. Meer specifiek, om per e-mail te melden wanneer een inkomende oproep naar de wachtrij ging, maar niemand (van de agenten) deze oproep beantwoordde.
Tot onze verbazing ontdekten we geen standaardmiddelen om deze taak in FreePBX op te lossen. Hoe we deze taak hebben aangepakt, zal ik hieronder uitleggen.
Voorwoord
Voordat we de taak 'frontaal' aanpakten, hebben we natuurlijk informatie op internet gezocht, maar we hebben geen kant-en-klare oplossing gevonden (misschien zochten we niet goed, maar wat kun je eraan doen...).
De vaardigheden om rechtstreeks met Asterisk te werken zijn niet zo talrijk als we zouden willen, dus de oplossing die wordt voorgesteld , was niet volledig doordacht en werd afgewezen.
We vonden de oplossing die werd voorgesteld, , leuk, maar die werkte niet. Hieruit hebben we opgemerkt dat werken in Asterisk moet gebeuren in de context van wachtrijen [ext-queues]. Aangezien we in FreePBX werken, moet dit gedaan worden in het configuratiebestand 'extensions_override_freepbx.conf'. We merkten op dat het 'vangen van gemiste oproepen' handig is voor het gebeurtenisevent hangupcall (einde van de oproep).
Na het lezen van de discussie, , ontstond het idee dat we de CDR-variabele 'Disposition' voor alle agenten in de wachtrij moesten filteren. Na het lezen van de informatie zijn er duidelijke stappen naar voren gekomen voor het oplossen van de gegeven taak.
Wat hebben we:
We hebben FreePBX 13.0.197 dat Asterisk 13.12.1 gebruikt. De OS-versie is SHMZ release 6.6 (Final). De distributie is gebaseerd op CentOS.
In Asterisk is IVR (interactief stemmenu) ingesteld dat inkomende oproepen naar verschillende Queues (wachtrijen) verspreidt. Aan elke wachtrij zijn Agents (agenten) toegewezen, oftewel operators.
Theorie
Wat er gebeurt in Asterisk
Wanneer er een inkomende oproep naar Asterisk komt, komt deze oproep op de IVR. De beller maakt een keuze door een bepaald cijfer op de telefoon in te toetsen en komt in een specifieke wachtrij terecht. Vervolgens ontvangen alle vrije agenten in de wachtrij tegelijkertijd de oproep.
Om beter te begrijpen wat er op dit moment gebeurt en wat er daarna gebeurt, kijken we naar het Report CDR (Figuur 1).

Figuur 1
Wanneer een binnenkomend gesprek in de wachtrij komt, krijgt de variabele "Disposition" van alle agenten de waarde "NO ANSWER", als de agenten op dat moment niet bezet zijn. De variabele "Disposition" kan ook andere waarden aannemen (zie ), behalve de waarde "ANSWERED". Op het moment dat een van de agenten een binnenkomend gesprek beantwoordt, wordt de waarde van de variabele "Disposition" van deze agent "ANSWERED".
Uit het Report CDR is te zien dat wanneer het gesprek in de wachtrij komt (in de kolom App krijgt de waarde "Queue"), alle gebeurtenissen hetzelfde "uniqueid" hebben (kolom System).
Kort over CDR
Het is belangrijk om te begrijpen wat CDR is en op welk moment de gegevens in CDR worden vastgelegd, die we in het Report CDR observeren. CDR is, met betrekking tot het besturingssysteem, een database waarin Asterisk gedetailleerde gespreksrapporten opslaat (zie ). In ons geval is dit de database met de naam asteriskcdrdb, die zich in MySQL bevindt. Door ervaring hebben we vastgesteld dat de gegevens over een gesprek met een bepaald "uniqueid" niet onmiddellijk na het optreden van een gebeurtenis in asteriskcdrdb worden vastgelegd, maar pas na de hangupcall-gebeurtenis (einde van het gesprek).
Het principe van de werking van de gemaakte oplossing
Omdat we meer kennis hebben van bash dan van Asterisk, is de hoofdgedachte als volgt. Voordat de hangupcall-gebeurtenis zich voordoet, moet er een bash-script worden aangeroepen. In dit script worden 3 parameters doorgegeven. De eerste parameter is "uniqueid", voor het filteren van gegevens uit CDR. De tweede parameter is "CALLERID(num)" (het nummer van de beller), om te weten naar wie we moeten terugbellen. De derde parameter is "NODEST" (het nummer van de wachtrij), waarin het gesprek is binnengekomen, zodat we weten waar het gesprek over ging en naar wie we een e-mail met een melding over het gemiste gesprek moeten sturen.
Het bash-script moet verbinding maken met de asteriskcdrdb database in MySQL en alle waarden van de variabele "Disposition" met het bepaalde "uniqueid" ophalen. Van de verkregen gegevens moeten de waarden "NO ANSWER", "BUSY", "FAILED", "UNKNOWN" worden uitgesloten. In dat geval blijven er ofwel "ANSWERED" over - het binnenkomende gesprek is beantwoord, of er is helemaal niets - een gemist gesprek.
Als het gesprek gemist blijkt te zijn, moet het script een e-mailmelding versturen.
Laten we vooruitkijken en een belangrijk punt onder de aandacht brengen. Asterisk voert opdrachten sequentieel uit, wachtend op hun voltooiing (wat op zich logisch is). We zullen het bash-script aanroepen voordat de opdracht hangupcall wordt uitgevoerd. Op deze manier zal tijdens de uitvoering van het script de informatie over de gewenste 'uniqueid' nog niet in de CDR zijn ingevoerd. Om dit probleem op te lossen, zullen we het bash-script aanroepen met de parameter '&', zodat Asterisk meteen kan doorgaan naar de volgende stap, namelijk hangupcall. En aan het begin van het bash-script zullen we een kleine vertraging instellen om Asterisk de tijd te geven om de gegevens met de 'uniqueid' die we interessant vinden in de CDR in te voeren.
Praktijk
Voordat we verder gaan met de configuratie van Asterisk en het maken van het bash-script, moeten we de verzending van e-mailnotificaties instellen. Hiervoor gaan we de utility postfix gebruiken.
Postfix configureren
We hebben een maildomein 'lucky.ru', dat zich op Yandex bevindt. We zullen postfix instellen in de modus van een smtp-client en e-mails verzenden vanaf het account asterisk@lucky.ru.
Dit is de basis van de oplossing hier vandaan: .
Laten we eerst de pakketten installeren/bijwerken/controleren:
yum install postfix
yum install mailx
yum install cyrus-sasl cyrus-sasl-lib cyrus-sasl-plainWe zullen het hoofdconfiguratiebestand van postfix '/etc/postfix/main.cf' niet overschrijven, maar een back-up daarvan maken:
cp /etc/postfix/main.cf /etc/postfix/main.cf.savWe bewerken het bestand '/etc/postfix/main.cf' en stellen het in als volgt:
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
#####################Niet elke regel in '/etc/postfix/main.cf' kan worden gecommentarieerd. Commentaren in sommige regels worden niet door de parser herkend en worden ter verwerking doorgegeven, wat tot fouten leidt. Het is beter om commentaren in dit bestand te vermijden. Je kunt hier mee experimenteren door in een ander venster 'tail -f /var/log/messages' uit te voeren.
Ik wil de regel 'smtputf8_autodetect_classes = all' benadrukken. Deze vermelding schakelt standaard utf-8 in, waardoor het mogelijk is om zowel cyrillisch in de body van de e-mail als in de onderwerpregel te gebruiken zonder extra handelingen (zie. ).
Laten we een map maken voor de configuratiebestanden:
mkdir /etc/postfix/privateBewerken van het bestand «/etc/postfix/private/sender_relay». Hierin moet worden aangegeven naar welke smtp-server moet worden verwezen bij het gebruik van ons maildomein:
nano /etc/postfix/private/sender_relay
#####################
@lucky.ru smtp.yandex.ru
#####################Bewerken van het bestand «/etc/postfix/private/sasl_passwd». Hierin geven we het e-mailadres op dat we zullen gebruiken voor het verzenden van berichten, evenals de gebruikersnaam en het wachtwoord van dit account (gebruikersnaam en wachtwoord worden gescheiden door een dubbele punt):
nano /etc/postfix/private/sasl_passwd
#####################
asterisk@lucky.ru asterisk@lucky.ru:password_asterisk
#####################Bewerken van het bestand «/etc/postfix/generic». Hierin zullen we de regels voor het vervangen van het uitgaande adres opstellen (zie: ):
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
#####################Het oorspronkelijke uitgaande adres is afhankelijk van de inhoud van «/etc/hosts» en «/etc/hostname», evenals van de gebruikersnaam die de e-mail zal verzenden. Dat wil zeggen, ondanks dat we een smtp-client gebruiken en e-mails verzenden vanaf asterisk@lucky.ru, zal postfix aanvankelijk 'iets anders' invoegen in het afzendadres en dit moet worden gecorrigeerd met de regels van dit configuratiebestand.
Hier is de inhoud van mijn bestand «/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
#####################Het is belangrijk dat de server een domein heeft (waarde na het punt), omdat de mail-tool 'zoekt' naar de domeinnaam in «/etc/hosts» en als deze deze niet direct vindt, zal het dit nog enige tijd blijven doen voordat het de e-mail verzendt. Dat wil zeggen, als het domein niet is opgegeven, zal de e-mail met enkele minuten vertraging worden verzonden.
Hier is de inhoud van mijn bestand «/etc/hostname»:
cat /etc/hostname
#####################
asterisk
#####################Vervolgens moeten we de gemaakte configuratiebestanden omzetten naar geïndexeerde databases, hiervoor voeren we de volgende opdracht uit:
postmap /etc/postfix/generic && postmap /etc/postfix/private/{sasl_passwd,sender_relay}Daarna moeten we het certificaat smtp.yandex.ru downloaden en op de server plaatsen, hiervoor voeren we de volgende opdracht uit:
openssl s_client -starttls smtp -crlf -connect smtp.yandex.ru:25 > /etc/postfix/ca.pemMaar nadat de technische informatie op het scherm verschijnt, zal het team "blijven hangen". Druk op Ctrl+C om het te onderbreken.
Laten we nu handmatig al het afval uit het resulterende bestand verwijderen en alleen het certificaat behouden. Het moet er ongeveer zo uitzien:
nano /etc/postfix/ca.pem
#####################
-----BEGIN CERTIFICATE-----
MIIGazCCBVOgAwIBAgIQcUU9mJXW4OUs5Gf0JfLtsjANBgkqhkiG9w0BAQsFADBf
...
nRG0DfdqYIuPGApFORYe
-----END CERTIFICATE-----
#####################En laten we ten slotte postfix opnieuw opstarten:
service postfix restartWe sturen een testemail:
echo "Dit is de inhoud van de email" | mail -s "Dit is het onderwerp" admin@lucky.nladmin@lucky.nl — bestemmingsadres
De configuratie van postfix is hiermee afgerond.
We schrijven een bash-script
We maken een directory om het bash-script op te slaan (waar het ook maar het beste uitkomt):
mkdir /home/asterisk/scriptsWe maken een bestand voor het bash-script:
touch /home/asterisk/scripts/noanswer.shWe geven het scriptbestand uitvoeringsrechten:
chmod +x /home/asterisk/scripts/noanswer.shAls je twijfelt over de rechten van het bestand, kun je voor de debugging tijdelijk volledige toegang geven. Maar dat is "niet veilig".
chmod 777 /home/asterisk/scripts/noanswer.shDe tekst van het bash-script:
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.nl"
subject="over een belangrijk onderwerp"
;;
63100)
address="debian@lucky.nl"
subject="over Linux Debian"
;;
63200)
address="windows@lucky.nl"
subject="over Windows"
;;
63300)
address="freebsd@lucky.nl"
subject="over FreeBSD"
;;
63400)
address="ubuntu@lucky.nl"
subject="over Linux Ubuntu"
;;
63500)
address="centos@lucky.nl"
subject="over Linux CentOS"
;;
*)
address="admin@lucky.nl"
error_kod=1
;;
esac
case $error_kod in
0)
echo "Gemiste oproep van abonnee $2, die $subject belde." | mail -s "Gemiste oproep van $2" $address
echo "Gemiste oproep voor $address van abonnee $2, die $subject belde. uid=$1" | mail -s "Gemiste oproep van $2" admin@lucky.nl
;;
1)
echo "Gemiste oproep van $2. Onbekende wachtrij. uid=$1" | mail -s "Gemiste oproep van $2" admin@lucky.nl
;;
esac
fi
#####################Korte uitleg van het script:
"sleep 7":
Dit is de vertraging in tijd waarover ik eerder sprak. We hebben een vertraging ingesteld van 7 seconden. Hoewel, ik denk dat één seconde ook voldoende zou zijn.
"res_sql="SELECT disposition FROM cdr WHERE uniqueid = '$1'":We hebben de MySQL-query in een aparte variabele geplaatst voor het gemak.
Vervolgens doen we een aanvraag in mysql en filteren we de verkregen output. We verwijderen alle opties behalve "ANSWERED", als deze überhaupt aanwezig is. Als er meerdere waarden "ANSWERED" zijn, laten we er slechts één over. Aan het einde krijgen we in de variabele "answer" ofwel "ANSWERED" ofwel "".
Als de waarde van de variabele "answer" niet gelijk is aan "ANSWERED", dan is dit een gemiste oproep. Afhankelijk van het nummer in de wachtrij, geven we met de case-operator het adres op waarheen de e-mail notificatie moet worden verzonden, en wat er in dit bericht moet worden geschreven (de wijzigbare gedeelte van het bericht).
Hier bekijken we de situatie waarbij de wachtrij is ingesteld in Asterisk, maar niet in het script is beschreven. In dit geval ontvangt admin@lucky.ru een e-mail dat de wachtrij onbekend is voor het script.
Als de wachtrij echter is beschreven, wordt de e-mail naar de juiste bestemming gestuurd en een duplicaat wordt naar admin@lucky.ru gestuurd met de vermelding van "uniqueid", zodat de gebeurtenissen van deze oproep indien nodig kunnen worden gevolgd.
Met dit is het script afgelopen.
Ik wil opmerken dat we voor de verbinding met mysql de gebruikersnaam en het wachtwoord hebben gebruikt die we van tevoren hebben verkregen. Voer in FreePBX de volgende opdracht uit om de gebruikersnaam van de Asterisk-gebruiker in mysql te leren kennen:
cat /etc/amportal.conf | grep AMPDBUSEREn om het wachtwoord van de Asterisk-gebruiker in mysql te achterhalen, voert u de volgende opdracht uit:
cat /etc/amportal.conf | grep AMPDBPASSAsterisk configuratie
We gebruiken FreePBX. In FreePBX zijn er verschillende soorten configuratiebestanden (zie ), sommige van deze bestanden worden door FreePBX overschreven bij herstart, andere niet (ze worden custom genoemd), omdat ze speciaal voor de gebruiker zijn bedoeld.
We zullen werken met het configuratiebestand "extensions_override_freepbx.conf", aangezien dit onder de custom type valt.
Laten we eerst controleren of het bestand "\/etc\/asterisk\/extensions.conf" het bestand "extensions_override_freepbx.conf" vastlegt. Voer hiervoor de volgende opdracht uit:
cat /etc/asterisk/extensions.conf | grep extensions_override_freepbx.conf
#####################
#include extensions_override_freepbx.conf
#####################Laten we het bestand "\/etc\/asterisk\/extensions_override_freepbx.conf" bewerken en het als volgt opstellen:
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,)
#####################Zoals ik eerder schreef, is het symbool «&» aan het einde verplicht. Omdat we in een bash-script met CDR-gegevens rechtstreeks uit de MySQL-database gaan werken, en deze gegevens pas in MySQL worden ingevoerd na het uitvoeren van «exten => h,2,Macro(hangupcall,)», is het noodzakelijk om niet te wachten tot de uitvoering van het bash-script is voltooid, maar over te gaan naar de volgende stap in Asterisk. Het bash-script zelf moet een tijdvertraging bevatten voordat de hoofdonderdelen worden uitgevoerd.
Om de wijzigingen in het configuratiebestand «/etc/asterisk/extensions_override_freepbx.conf» van kracht te laten worden, moet de Asterisk-kernel opnieuw worden opgestart met de volgende opdracht:
/usr/sbin/asterisk -rx "core restart now"Dit moet worden gedaan nadat het bash-script is aangemaakt.
Conclusie
Misschien is dit wel de 1001e manier om 'gemiste oproepen' in Asterisk te vangen. Deel in de opmerkingen hoe jullie deze taak aanpakken. En wat, volgens jou, kan verbeterd / herschreven / geoptimaliseerd worden. We zouden dankbaar zijn voor constructieve ideeën.
Bron: habr.com
