
IP-PBX Asterisk ist ein leistungsstarker Kombi in der Welt der IP-Telefonie. Die Web-Schnittstelle FreePBX, die für Asterisk entwickelt wurde, erleichtert die Konfiguration erheblich und senkt die Einstiegshürde für das System.
Wenn Sie eine Aufgabe im Zusammenhang mit IP-Telefonie vorstellen können, lässt sich diese höchstwahrscheinlich in Asterisk umsetzen. Seien Sie jedoch darauf vorbereitet, dass Sie Entschlossenheit und Durchhaltevermögen benötigen.
Wir standen vor der Aufgabe, E-Mail-Benachrichtigungen über versäumte Anrufe einzurichten. Genauer gesagt, sollten wir per E-Mail über Situationen informiert werden, in denen ein eingehender Anruf in die Warteschlange übergegangen ist, aber niemand (von den Agenten) auf diesen Anruf geantwortet hat.
Zu unserer Überraschung konnten wir in FreePBX keine integrierten Mittel zur Lösung dieser Aufgabe finden. Wie wir dieses Problem gelöst haben, werde ich im folgenden Abschnitt erklären.
Vorwort
Bevor wir die Lösung direkt angegangen sind, haben wir natürlich im Internet nach Informationen gesucht, aber keine schlüsselfertige Lösung gefunden (vielleicht haben wir nicht gut genug gesucht, aber was soll’s…).
Es gibt nicht so viele Fähigkeiten im direkten Umgang mit Asterisk, wie wir uns wünschen würden, daher wurde die angebotene Lösung , nicht vollständig durchdacht und verworfen.
Ich mochte die vorgeschlagene Lösung , obwohl sie nicht funktioniert hat. Dabei wurde betont, dass man in Asterisk im Kontext der Warteschlangen [ext-queues] arbeiten muss. Da wir FreePBX verwenden, erfolgt die Arbeit in der Konfigurationsdatei „extensions_override_freepbx.conf“. Es wurde festgestellt, dass es praktisch ist, „verpasste Anrufe zu erfassen“ vor dem Ereignis hangupcall (Anrufbeendigung).
Nachdem ich die Diskussion gelesen habe , kam die Idee auf, dass die CDR-Variable „Disposition“ für alle Agenten in der Warteschlange gefiltert werden sollte. Nach dem Lesen der Informationen haben sich sehr konkrete Schritte zur Lösung der gestellten Aufgabe herausgebildet.
Was wir haben:
Wir haben FreePBX 13.0.197, das Asterisk 13.12.1 verwendet. Die OS-Version ist SHMZ release 6.6 (Final). Die Distribution basiert auf CentOS.
In Asterisk ist ein IVR (Interactive Voice Response) eingerichtet, das eingehende Anrufe auf verschiedene Warteschlangen verteilt. Jeder Warteschlange sind Agenten zugeordnet, d.h. Operatoren.
Theorie
Was in Asterisk passiert
Wenn ein eingehender Anruf bei Asterisk eingeht, landet dieser Anruf im IVR. Der Anrufer wählt eine bestimmte Ziffer auf dem Telefon und gelangt in eine bestimmte Warteschlange. Danach erhalten alle freien Agenten der Warteschlange gleichzeitig den Anruf.
Um besser zu verstehen, was in diesem Moment passiert und wie es weitergeht, werfen wir einen Blick auf den Report CDR (Abb. 1).

Abb. 1
Wenn ein eingehender Anruf in die Warteschlange gelangt, ist der Wert der Variable „Disposition“ für alle Agenten gleich „NO ANSWER“, sofern die Agenten zu diesem Zeitpunkt nicht beschäftigt sind. Die Variable „Disposition“ konnte auch andere Werte annehmen (siehe ), außer dem Wert „ANSWERED“. In dem Moment, in dem einer der Agenten den eingehenden Anruf entgegennimmt, wird der Wert der Variable „Disposition“ dieses Agenten gleich „ANSWERED“.
Aus dem Report CDR lässt sich erkennen, dass, wenn der Anruf in die Warteschlange übergeht (in der Spalte App wird der Wert gleich „Queue“), alle Ereignisse mit der gleichen „uniqueid“ (Spalte System) erscheinen.
Kurzinformation zu CDR
Es ist wichtig zu verstehen, was CDR ist und in welchem Moment die Daten in CDR eingegeben werden, die wir im Report CDR beobachten. CDR ist, relativ zum Betriebssystem, eine Datenbank, in die Asterisk detaillierte Anrufberichte aufzeichnet (siehe ). In unserem Fall handelt es sich um die Datenbank namens asteriskcdrdb, die sich in MySQL befindet. Durch Erfahrung haben wir festgestellt, dass die Anrufdaten mit einer bestimmten „uniqueid“ nicht sofort nach dem Auftreten eines Ereignisses in asteriskcdrdb gespeichert werden, sondern erst nach dem Ereignis hangupcall (Ende des Anrufs).
Funktionsprinzip der entwickelten Lösung
Da wir in Bash mehr Kenntnisse haben als in Asterisk, lautet die grundlegende Idee wie folgt. Vor dem Ereignis hangupcall soll ein Bash-Skript aufgerufen werden. In dieses Skript übergeben wir 3 Parameter. Der erste Parameter ist „uniqueid“, um die aus dem CDR erhaltenen Daten zu filtern. Der zweite Parameter ist „CALLERID(num)“ (die Nummer des Anrufers), um zu wissen, wem wir zurückrufen. Der dritte Parameter ist „NODEST“ (die Nummer der Warteschlange), in die der Anruf einging, um zu wissen, worum es beim Anruf ging, und um die E-Mail-Benachrichtigung über den verpassten Anruf zu versenden.
Das Bash-Skript muss sich mit der Datenbank asteriskcdrdb in MySQL verbinden und alle Werte der Variablen „Disposition“ mit einer bestimmten „uniqueid“ abrufen. Aus den erhaltenen Daten müssen die Werte „NO ANSWER“, „BUSY“, „FAILED“ und „UNKNOWN“ ausgeschlossen werden. Am Ende bleiben entweder „ANSWERED“ — der eingehende Anruf wurde entgegengenommen, oder es bleibt nichts — der Anruf wurde verpasst.
Wenn ein Anruf verpasst wurde, sollte das Skript eine E-Mail-Benachrichtigung senden.
Um einen wichtigen Punkt vorwegzunehmen: Asterisk führt die Befehle nacheinander aus und wartet auf deren Abschluss (was grundsätzlich logisch ist). Der bash-Skript wird jedoch aufgerufen, bevor der Befehl hangupcall ausgeführt wird. Daher wird zum Zeitpunkt der Ausführung des Skripts noch keine Information über die gesuchte «uniqueid» in den CDR eingetragen sein. Um dieses Problem zu lösen, werden wir den bash-Skript mit dem Parameter «&» aufrufen, damit Asterisk sofort mit dem nächsten Schritt, also hangupcall, fortfahren kann. Am Anfang des bash-Skripts setzen wir eine kurze Verzögerung, um Asterisk Zeit zu geben, die Daten mit der interessierenden «uniqueid» in den CDR einzutragen.
Praxis
Bevor wir mit der Konfiguration von Asterisk und der Erstellung des bash-Skripts beginnen, müssen wir die E-Mail-Benachrichtigungen einrichten. Dazu verwenden wir das Dienstprogramm postfix.
Postfix-Konfiguration
Wir haben die Domain «lucky.ru», die bei Yandex gehostet wird. Wir konfigurieren postfix im SMTP-Client-Modus und senden E-Mails von dem Konto asterisk@lucky.ru.
Hierbei handelt es sich um eine Lösung von hier: .
Zuerst installieren/aktualisieren/prüfen wir die Verfügbarkeit der Pakete:
yum install postfix
yum install mailx
yum install cyrus-sasl cyrus-sasl-lib cyrus-sasl-plainWir werden die Hauptkonfigurationsdatei von Postfix «/etc/postfix/main.cf» nicht überschreiben, sondern eine Sicherungskopie erstellen:
cp /etc/postfix/main.cf /etc/postfix/main.cf.savBearbeiten Sie die Datei «/etc/postfix/main.cf» und bringen Sie sie in die folgende 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
#####################Nicht jede Zeile in «/etc/postfix/main.cf» kann kommentiert werden. Kommentare in einigen Zeilen werden vom Parser nicht erkannt und an die Verarbeitung übergeben, was zu Fehlern führt. Es ist besser, auf Kommentare innerhalb dieser Datei zu verzichten. Sie können damit experimentieren, indem Sie in einem anderen Fenster «tail -f /var/log/messages» ausführen.
Ich möchte auf die Zeile «smtputf8_autodetect_classes = all» hinweisen. Diese Einstellung aktiviert standardmäßig UTF-8, was es ermöglicht, kyrillische Schriftzeichen sowohl im Text als auch im Betreff der E-Mail ohne zusätzliche Manipulationen zu verwenden (Siehe. ).
Lassen Sie uns ein Verzeichnis für die Konfigurationsdateien erstellen:
mkdir /etc/postfix/privateWir bearbeiten die Datei «/etc/postfix/private/sender_relay». Hier geben wir an, auf welchen SMTP-Server verwiesen werden soll, wenn wir unsere Mail-Domain verwenden:
nano /etc/postfix/private/sender_relay
#####################
@lucky.ru smtp.yandex.ru
#####################Wir bearbeiten die Datei «/etc/postfix/private/sasl_passwd». Hier geben wir die E-Mail-Adresse an, die wir zum Versenden von Nachrichten verwenden werden, sowie den Benutzernamen und das Passwort für dieses Konto (Benutzername und Passwort durch einen Doppelpunkt trennen):
nano /etc/postfix/private/sasl_passwd
#####################
asterisk@lucky.ru asterisk@lucky.ru:password_asterisk
#####################Wir bearbeiten die Datei «/etc/postfix/generic». Hier schreiben wir die Regeln für die Umleitung der Absenderadresse (siehe. ):
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
#####################Die ursprüngliche Absenderadresse hängt vom Inhalt von "/etc/hosts" und "/etc/hostname" sowie vom Benutzernamen ab, der die E-Mail senden wird. Das heißt, obwohl wir einen SMTP-Client verwenden und E-Mails von asterisk@lucky.ru senden, wird Postfix dennoch anfangs "etwas Eigenes" in die Absenderadresse einfügen, was über die Regeln in dieser Konfigurationsdatei korrigiert werden muss.
Hier ist der Inhalt meiner Datei "/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
#####################Es ist wichtig, dass der Server eine Domain hat (den Wert nach dem Punkt), da das Mail-Utility nach dem Domainnamen in "/etc/hosts" sucht. Wenn es ihn nicht sofort findet, wird es weitere Minuten danach suchen, bevor die E-Mail gesendet wird. Das heißt, wenn die Domain nicht eingetragen ist, wird die E-Mail mit mehreren Minuten Verzögerung versendet.
Hier ist der Inhalt meiner Datei "/etc/hostname":
cat /etc/hostname
#####################
asterisk
#####################Anschließend müssen die erstellten Konfigurationsdateien in indizierte Datenbanken überführt werden. Dazu führen wir den folgenden Befehl aus:
postmap /etc/postfix/generic && postmap /etc/postfix/private/{sasl_passwd,sender_relay}Als Nächstes müssen wir das Zertifikat smtp.yandex.ru herunterladen und auf dem Server ablegen. Führen Sie dazu den folgenden Befehl aus:
openssl s_client -starttls smtp -crlf -connect smtp.yandex.ru:25 > /etc/postfix/ca.pemNachdem technische Informationen angezeigt wurden, wird der Befehl "weiterhin hängen" bleiben. Drücken Sie Ctrl+C, um ihn abzubrechen.
Jetzt entfernen wir manuell den gesamten Müll aus der resultierenden Datei und lassen nur das Zertifikat übrig. Es sollte etwa wie folgt aussehen:
nano /etc/postfix/ca.pem
#####################
-----BEGIN CERTIFICATE-----
MIIGazCCBVOgAwIBAgIQcUU9mJXW4OUs5Gf0JfLtsjANBgkqhkiG9w0BAQsFADBf
...
nRG0DfdqYIuPGApFORYe
-----END CERTIFICATE-----
#####################Und schließlich starten wir Postfix neu:
service postfix restartWir senden eine Test-E-Mail:
echo "Dies ist der E-Mail-Text" | mail -s "Das ist das Thema" admin@lucky.ruadmin@lucky.ru – Zieladresse
Damit ist die Konfiguration von Postfix abgeschlossen.
Wir schreiben ein Bash-Skript
Erstellen Sie ein Verzeichnis für das Bash-Skript (dort, wo es Ihnen am besten gefällt):
mkdir /home/asterisk/scriptsErstellen Sie die Bash-Skriptdatei:
touch /home/asterisk/scripts/noanswer.shGeben Sie der Skriptdatei Ausführungsrechte:
chmod +x /home/asterisk/scripts/noanswer.shWenn Sie Zweifel an den Rechten der Datei haben, können Sie während der Fehlersuche vorübergehend vollen Zugriff auf die Datei gewähren. Aber das ist „nicht sicher“.
chmod 777 /home/asterisk/scripts/noanswer.shText des Bash-Skripts:
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="zu einem wichtigen Thema"
;;
63100)
address="debian@lucky.ru"
subject="zu Fragen zu Linux Debian"
;;
63200)
address="windows@lucky.ru"
subject="zu Fragen zu Windows"
;;
63300)
address="freebsd@lucky.ru"
subject="zu Fragen zu FreeBSD"
;;
63400)
address="ubuntu@lucky.ru"
subject="zu Fragen zu Linux Ubuntu"
;;
63500)
address="centos@lucky.ru"
subject="zu Fragen zu Linux CentOS"
;;
*)
address="admin@lucky.ru"
error_kod=1
;;
esac
case $error_kod in
0)
echo "Verpasster Anruf von $2, der über $subject anrief." | mail -s "Verpasster Anruf von $2" $address
echo "Verpasster Anruf für $address von $2, der über $subject anrief. uid=$1" | mail -s "Verpasster Anruf von $2" admin@lucky.ru
;;
1)
echo "Verpasster Anruf von $2. Unbekannte Warteschlange. uid=$1" | mail -s "Verpasster Anruf von $2" admin@lucky.ru
;;
esac
fi
#####################Kurze Analyse des Skripts:
„sleep 7“:
Das ist die Zeitverzögerung, von der ich zuvor gesprochen habe. Wir haben eine Verzögerung von 7 Sekunden festgelegt. Ich denke, dass auch eine Sekunde völlig ausreichend wäre.
„res_sql="SELECT disposition FROM cdr WHERE uniqueid = '$1'"“:Wir haben die MySQL-Anfrage in eine separate Variable ausgegliedert, um die Handhabung zu erleichtern.
Anschließend führen wir die MySQL-Anfrage aus und filtern die erhaltenen Ergebnisse. Wir entfernen alle Optionen außer „ANSWERED“, sofern verfügbar. Falls mehrere Werte „ANSWERED“ vorhanden sind, muss nur einer beibehalten werden. Am Ende erhalten wir in der Variable „answer“ entweder „ANSWERED“ oder einen leeren Wert.
Wenn der Wert der Variable „answer“ nicht „ANSWERED“ ist, wird dies als verpasster Anruf gewertet. Je nach Warteschennummer legen wir mit dem Falloperator fest, an wen genau die E-Mail-Benachrichtigung gesendet werden muss und was in dieser Nachricht geschrieben werden soll (veränderlicher Teil der Nachricht).
Im Folgenden betrachten wir den Fall, in dem die Warteschlange in Asterisk definiert ist, aber nicht im Skript beschrieben wird. In diesem Fall erhält admin@lucky.ru eine E-Mail, dass die Warteschlange dem Skript nicht bekannt ist.
Wenn die Warteschlange hingegen beschrieben ist, wird die E-Mail an die vorgesehene Adresse gesendet und eine Kopie an admin@lucky.ru mit dem „uniqueid“ gesendet, damit die Ereignisse für diesen Anruf bei Bedarf nachverfolgt werden können.
Damit endet das Skript.
Ich möchte anmerken, dass wir für die Verbindung zu MySQL den Benutzernamen und das Passwort verwendet haben, die wir im Voraus herausgefunden haben. In FreePBX können Sie den Benutzernamen für Asterisk in MySQL mit folgendem Befehl herausfinden:
cat /etc/amportal.conf | grep AMPDBUSERUm das Passwort für den Asterisk-Benutzer in MySQL herauszufinden, verwenden Sie bitte folgenden Befehl:
cat /etc/amportal.conf | grep AMPDBPASSAsterisk-Konfiguration
Wir verwenden FreePBX. In FreePBX gibt es verschiedene Typen von Konfigurationsdateien (siehe ), einige davon werden von FreePBX beim Neustart überschrieben, während andere nicht überschrieben werden (diese werden als benutzerdefiniert bezeichnet), da sie speziell für den Benutzer vorgesehen sind.
Wir werden mit der Konfigurationsdatei „extensions_override_freepbx.conf“ arbeiten, da sie als benutzerdefiniert gilt.
Zunächst stellen wir sicher, dass die Datei „/etc/asterisk/extensions.conf“ die Datei „extensions_override_freepbx.conf“ eingebunden hat. Führen Sie dazu folgenden Befehl aus:
cat /etc/asterisk/extensions.conf | grep extensions_override_freepbx.conf
#####################
#include extensions_override_freepbx.conf
#####################Bearbeiten Sie die Datei „/etc/asterisk/extensions_override_freepbx.conf“ und passen Sie sie wie folgt an:
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,)
#####################Wie ich bereits erwähnt habe, ist das Symbol „&“ am Ende erforderlich. Da wir in einem Bash-Skript mit CDR-Daten direkt aus einer MySQL-Datenbank arbeiten werden und diese Daten nur nach der Ausführung von „exten => h,2,Macro(hangupcall,)“ in MySQL eingefügt werden, ist es notwendig, nicht auf das Ende der Bash-Skript-Ausführung zu warten, sondern zum nächsten Schritt in Asterisk überzugehen. Das Bash-Skript selbst sollte eine zeitliche Verzögerung vor der Ausführung seines Hauptteils enthalten.
Um die Änderungen in der Konfigurationsdatei „/etc/asterisk/extensions_override_freepbx.conf“ wirksam zu machen, muss der Asterisk-Kernel mit dem folgenden Befehl neu gestartet werden:
/usr/sbin/asterisk -rx "core restart now"Dies sollte erfolgen, nachdem das Bash-Skript erstellt wurde.
Fazit
Dies ist wahrscheinlich die 1001. Methode zum „Abfangen verpasster Anrufe“ in Asterisk. Teilen Sie in den Kommentaren mit, wie Sie diese Aufgabe lösen. Und was Ihrer Meinung nach verbessert / umgestaltet / optimiert werden kann. Wir würden uns über konstruktive Ideen freuen.
Quelle: habr.com
