
IP ATC Asterisk ist eine leistungsstarke Maschine im Bereich der IP-Telefonie. Und die für Asterisk erstellte FreePBX-Weboberfläche vereinfacht die Einrichtung erheblich und verringert die Eintrittsbarriere in das System.
Wenn Ihnen eine Aufgabe im Zusammenhang mit IP-Telefonie einfällt, dann ist diese mit ziemlicher Sicherheit in Asterisk umsetzbar. Aber seien Sie versichert, dass Sie Ausdauer und Durchhaltevermögen brauchen werden.
Wir standen vor der Aufgabe, E-Mail-Benachrichtigungen über verpasste Anrufe einzurichten. Genauer gesagt, benachrichtigen Sie per E-Mail über die Fälle, in denen ein eingehender Anruf in die Warteschlange gestellt wurde, aber niemand (der Agenten) diesen eingehenden Anruf beantwortet hat.
Überraschenderweise haben wir in FreePBX keine Standardtools zur Lösung dieses Problems gefunden. Im Folgenden erzähle ich euch, wie wir dieses Problem gelöst haben.
Vorwort
Bevor wir das Problem direkt gelöst haben, haben wir natürlich im Internet nach Informationen gesucht, aber keine schlüsselfertige Lösung gefunden (vielleicht haben wir nicht gut gesucht, aber was können Sie tun?).
Es gibt nicht so viele Fähigkeiten, direkt in Asterisk zu arbeiten, wie wir es gerne hätten, daher die angebotene Lösung wurde nicht vollständig verstanden und verworfen.
Mir gefiel die vorgeschlagene Lösung , obwohl es nicht funktioniert hat. Daher wurde betont, dass man in Asterisk im Kontext von Warteschlangen [ext-queues] arbeiten muss. Und da wir in Freepbx arbeiten, müssen wir in der Konfigurationsdatei „extensions_override_freepbx.conf“ arbeiten. Wir haben festgestellt, dass es praktisch ist, verpasste Anrufe vor dem Hangupcall-Ereignis (Ende des Anrufs) abzufangen.
Nachdem ich die Diskussion gelesen habe kam die Idee auf, dass es notwendig sei, die Variable „Disposition“ im CDR nach allen Agenten in der Warteschlange zu filtern. Und nach dem Lesen Informationen wurden ganz konkrete Schritte zur Lösung des Problems formuliert.
Was wir haben:
Es gibt FreePBX 13.0.197, das Asterisk 13.12.1 nutzt. Betriebssystemversion SHMZ Release 6.6 (Final). Die Distribution basiert auf CentOS.
Asterisk ist mit einem IVR (Sprachmenü) konfiguriert, das eingehende Anrufe auf verschiedene Warteschlangen verteilt. Jeder Warteschlange sind Agenten, also Operatoren, zugeordnet.
Теория
Was passiert in Asterisk?
Wenn Asterisk einen eingehenden Anruf erhält, wird der Anruf an das IVR weitergeleitet. Der Anrufer trifft eine Auswahl, indem er eine bestimmte Nummer auf dem Telefon drückt, und wird in eine bestimmte Warteschlange eingereiht. Danach erhalten alle freien Agenten in der Warteschlange gleichzeitig einen Anruf.
Um besser zu verstehen, was in diesem Moment passiert und was als nächstes passiert, wenden wir uns dem Report CDR zu (Abb. 1).

Ris.1
Wenn ein eingehender Anruf in die Warteschlange gelangte, wurde der Wert der Variablen „Disposition“ für alle Agenten auf „KEINE ANTWORT“ gesetzt, wenn die Agenten zu diesem Zeitpunkt nicht beschäftigt waren. Die Variable „Disposition“ könnte auch andere Werte annehmen (siehe. ), mit Ausnahme des Werts „ANSWERED“. Und in dem Moment, in dem einer der Agenten einen eingehenden Anruf beantwortet, wird der Wert der Variable „Disposition“ dieses Agenten gleich „ANTWORTET“.
Aus dem CDR-Bericht können Sie ersehen, dass alle Ereignisse mit derselben „uniqueid“ (Spalte „System“) angezeigt werden, wenn der Anruf in die Warteschlange gestellt wird (der Wert in der Spalte „App“ entspricht „Warteschlange“).
Kurz über CDR
Es ist wichtig zu verstehen, was ein CDR ist und an welchem Punkt genau die Daten, die wir im Report CDR beobachten, in das CDR eingegeben werden. Der CDR ist, bezogen auf das Betriebssystem, eine Datenbank, in die Asterisk einen detaillierten Anrufbericht schreibt (siehe. ). In unserem Fall handelt es sich um eine Datenbank namens asteriskcdrdb, die sich in MySQL befindet. Wir haben empirisch festgestellt, dass Daten zu einem Anruf mit einer bestimmten „uniqueid“ nicht unmittelbar nach dem Eintreten eines Ereignisses, sondern nach dem Hangupcall-Ereignis (Ende des Anrufs) in asteriskcdrdb eingegeben werden.
Das Funktionsprinzip der erstellten Lösung
Da wir mehr Kenntnisse in Bash als in Asterisk haben, stellte sich die Grundidee wie folgt heraus. Rufen Sie vor dem Hangupcall-Ereignis ein Bash-Skript auf. Übergeben Sie 3 Parameter an dieses Skript. Der erste Parameter ist „uniqueid“, um die vom CDR empfangenen Daten zu filtern. Der zweite Parameter ist „CALLERID(num)“ (Anrufernummer), um zu wissen, wen man zurückrufen soll. Der dritte Parameter ist „NODEST“ (Warteschlangennummer), in dem der Anruf eingegangen ist, um zu erfahren, um welches Problem es bei dem Anruf ging und an wen eine E-Mail-Benachrichtigung über den verpassten Anruf gesendet werden soll.
Das Bash-Skript muss eine Verbindung zur Datenbank asteriskcdrdb in MySQL herstellen und alle Werte der Variablen „Disposition“ mit einer bestimmten „uniqueid“ übernehmen. Aus den empfangenen Daten müssen Sie die folgenden Werte ausschließen: „KEINE ANTWORT“, „BUSY“, „FEHLGESCHLAGEN“, „UNBEKANNT“. Als Ergebnis bleibt entweder „ANTWORT“ – der eingehende Anruf wurde beantwortet, oder gar nichts – ein verpasster Anruf.
Wenn der Anruf verpasst wird, sollte das Skript als Nächstes eine E-Mail-Benachrichtigung senden.
Mit Blick auf die Zukunft werde ich einen wichtigen Punkt anmerken. Asterisk führt Befehle nacheinander aus und wartet auf deren Abschluss (was im Allgemeinen logisch ist). Und wir rufen das Bash-Skript auf, bevor der Befehl hangupcall ausgeführt wird. Daher werden zum Zeitpunkt der direkten Ausführung des Skripts keine Informationen über die gesuchte „uniqueid“ in das CDR eingegeben. Um dieses Problem zu lösen, rufen wir das Bash-Skript mit dem Parameter „&“ auf, sodass Asterisk sofort mit dem nächsten Schritt, nämlich dem Hangupcall, fortfährt. Und innerhalb des Bash-Skripts werden wir ganz am Anfang eine kleine Zeitverzögerung einstellen, um Asterisk Zeit zu geben, Daten mit der für uns interessanten „uniqueid“ in den CDR einzugeben.
Praxis
Bevor Sie mit der Konfiguration von Asterisk und der Erstellung eines Bash-Skripts fortfahren, müssen Sie den Versand von E-Mail-Benachrichtigungen konfigurieren. Dazu verwenden wir das Postfix-Dienstprogramm.
Postfix einrichten
Wir haben eine Maildomäne „lucky.ru“ in Yandex. Wir konfigurieren Postfix im SMTP-Client-Modus und senden Briefe vom Konto asterisk@lucky.ru.
Die Lösung basiert darauf: .
Lassen Sie uns zunächst Pakete installieren/aktualisieren/überprüfen:
yum install postfix
yum install mailx
yum install cyrus-sasl cyrus-sasl-lib cyrus-sasl-plainÜberschreiben wir nicht die Haupt-Postfix-Konfigurationsdatei „/etc/postfix/main.cf“, sondern erstellen wir eine Sicherungskopie davon:
cp /etc/postfix/main.cf /etc/postfix/main.cf.savWir bearbeiten die Datei „/etc/postfix/main.cf“ und bringen sie in 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 zur Verarbeitung weitergeleitet, was zu Fehlern führt. Es ist besser, Kommentare in dieser Datei abzulehnen. Sie können damit experimentieren, indem Sie im nächsten Fenster „tail -f /var/log/messages“ ausführen.
Ich werde die Zeile „smtputf8_autodetect_classes = all“ markieren. Dieser Eintrag enthält standardmäßig utf-8, was Ihnen die Verwendung von Kyrillisch sowohl im Textkörper als auch im Betreff des Briefes ohne zusätzliche Manipulationen ermöglicht (siehe. ).
Erstellen wir ein Verzeichnis für Konfigurationsdateien:
mkdir /etc/postfix/privateBearbeiten Sie die Datei „/etc/postfix/private/sender_relay“. Darin müssen Sie angeben, zu welchem SMTP-Server Sie eine Verbindung herstellen müssen, wenn Sie unsere Mail-Domain verwenden:
nano /etc/postfix/private/sender_relay
#####################
@lucky.ru smtp.yandex.ru
#####################Bearbeiten Sie die Datei „/etc/postfix/private/sasl_passwd“. Darin geben wir die E-Mail-Adresse an, die wir zum Versenden von Briefen verwenden, sowie den Benutzernamen und das Passwort für dieses Konto (wir geben den Benutzernamen und das Passwort durch einen Doppelpunkt getrennt an):
nano /etc/postfix/private/sasl_passwd
#####################
asterisk@lucky.ru asterisk@lucky.ru:password_asterisk
#####################Bearbeiten Sie die Datei „/etc/postfix/generic“. Darin werden wir die Regeln zum Ersetzen der ausgehenden Adresse aufschreiben (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 anfängliche Ausgangsadresse hängt vom Inhalt von "/etc/hosts" und "/etc/hostname" sowie vom Namen des Benutzers ab, der den Brief senden wird. Das heißt, obwohl wir einen SMTP-Client verwenden und Briefe von asterisk@lucky.ru senden, ersetzt Postfix zunächst "etwas Eigenes" in der Absenderadresse. Dies muss mithilfe der Regeln in dieser Konfigurationsdatei korrigiert werden.
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 über eine Art Domäne verfügt (den Wert nach dem Punkt), da das Mail-Dienstprogramm in „/etc/hosts“ nach dem Domänennamen „sucht“ und, wenn es ihn nicht sofort „findet“, ihn Er wird dies noch einige Minuten lang tun und erst dann den Brief abschicken. Das heißt, wenn die Domain nicht registriert ist, wird der Brief mit einer Verzögerung von mehreren Minuten versendet.
Hier ist der Inhalt meiner Datei „/etc/hostname“:
cat /etc/hostname
#####################
asterisk
#####################Als nächstes müssen Sie die erstellten Konfigurationsdateien in indizierte Datenbanken übertragen; führen Sie dazu 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 platzieren; führen Sie dazu den folgenden Befehl aus:
openssl s_client -starttls smtp -crlf -connect smtp.yandex.ru:25 > /etc/postfix/ca.pemAber nachdem die technischen Informationen auf dem Bildschirm angezeigt werden, bleibt der Befehl „hängen“. Drücken Sie Strg+C, um den Vorgang abzubrechen.
Lassen Sie uns nun manuell den gesamten Müll aus der resultierenden Datei entfernen und nur das Zertifikat belassen. Es sollte ungefähr so aussehen:
nano /etc/postfix/ca.pem
#####################
-----BEGIN CERTIFICATE-----
MIIGazCCBVOgAwIBAgIQcUU9mJXW4OUs5Gf0JfLtsjANBgkqhkiG9w0BAQsFADBf
...
nRG0DfdqYIuPGApFORYe
-----END CERTIFICATE-----
#####################Und schließlich Postfix neu starten:
service postfix restartTestbrief versenden:
echo "Это тело письма" | mail -s "Это тема" admin@lucky.ruadmin@lucky.ru – Zieladresse
Damit ist die Posfix-Einrichtung abgeschlossen.
Schreiben eines Bash-Skripts
Erstellen Sie ein Verzeichnis zum Speichern des Bash-Skripts (hier gefällt es Ihnen am besten):
mkdir /home/asterisk/scriptsErstellen Sie eine Bash-Skriptdatei:
touch /home/asterisk/scripts/noanswer.shWir erteilen der Skriptdatei Berechtigungen zur Ausführung:
chmod +x /home/asterisk/scripts/noanswer.shWenn Zweifel an den Rechten einer Datei bestehen, können Sie beim Debuggen vollen Zugriff auf die Datei gewähren. Dies sei aber „nicht sicher“.
chmod 777 /home/asterisk/scripts/noanswer.shBash-Skripttext:
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="по важному вопросу"
;;
63100)
address="debian@lucky.ru"
subject="по вопросам linux debian"
;;
63200)
address="windows@lucky.ru"
subject="по вопросам windows"
;;
63300)
address="freebsd@lucky.ru"
subject="по вопросам freebsd"
;;
63400)
address="ubuntu@lucky.ru"
subject="по вопросам linux ubuntu"
;;
63500)
address="centos@lucky.ru"
subject="по вопросам linux centos"
;;
*)
address="admin@lucky.ru"
error_kod=1
;;
esac
case $error_kod in
0)
echo "Пропущен вызов от абонента $2, звонившего $subject." | mail -s "Пропущен вызов от $2" $address
echo "Пропущен вызов для $address от абонента $2, звонившего $subject. uid=$1" | mail -s "Пропущен вызов от $2" admin@lucky.ru
;;
1)
echo "Пропущен вызов от $2. Очередь неизвестна. uid=$1" | mail -s "Пропущен вызов от $2" admin@lucky.ru
;;
esac
fi
#####################Kurze Analyse des Drehbuchs:
„Schlaf 7“:
Dies ist die gleiche Zeitverzögerung, über die ich zuvor geschrieben habe. Wir haben eine Verzögerung von 7 Sekunden eingestellt. Obwohl ich denke, dass eine Sekunde ausreicht.
«res_sql="SELECT disposition FROM cdr WHERE uniqueid = '$1'"»:Der Einfachheit halber haben wir die Abfrage in MySQL in eine separate Variable verschoben.
Als nächstes führen wir eine Abfrage in MySQL durch und filtern die resultierende Ausgabe. Wir löschen alle Optionen außer „ANTWORT“, falls es überhaupt eine gibt. Bei mehreren „ANSWERED“-Werten sollte nur einer übrig bleiben. Am Ende erhalten wir entweder „ANSWERED“ oder „“ in der Variable „answer“.
Wenn der Wert der Variable „answer“ nicht „ANSWERED“ ist, handelt es sich um einen verpassten Anruf. Abhängig von der Warteschlangennummer geben wir mithilfe der Case-Anweisung die Adresse an, an die genau die E-Mail-Benachrichtigung gesendet werden soll, und was in diese Nachricht geschrieben werden soll (der variable Teil der Nachricht).
Als nächstes betrachten wir den Fall, dass die Warteschlange in Asterisk eingerichtet, aber nicht im Skript beschrieben ist. In diesem Fall erhält admin@lucky.ru eine E-Mail, dass die Warteschlange dem Skript unbekannt ist.
Wenn die Warteschlange beschrieben ist, wird ein Brief an das Ziel und ein Duplikat des Briefes an admin@lucky.ru mit der Angabe „uniqueid“ gesendet, sodass die Ereignisse dieses Anrufs bei Bedarf verfolgt werden können.
Hier endet das Skript.
Ich stelle fest, dass wir für die Verbindung zu MySQL einen Benutzernamen und ein Passwort verwendet haben, die wir im Voraus gelernt haben. Um in FreePBX die Asterisk-Benutzeranmeldung in MySQL herauszufinden, führen Sie den folgenden Befehl aus:
cat /etc/amportal.conf | grep AMPDBUSERUnd um das Asterisk-Benutzerpasswort in MySQL herauszufinden, führen Sie den folgenden Befehl aus:
cat /etc/amportal.conf | grep AMPDBPASSAsterisk einrichten
Wir nutzen FreePBX. FreePBX verfügt über verschiedene Arten von Konfigurationsdateien (siehe ), einige davon werden von FreePBX beim Neustart überschrieben, andere werden nicht überschrieben (sie werden als benutzerdefiniert bezeichnet), da sie speziell für den Benutzer entwickelt wurden.
Wir werden mit der Konfigurationsdatei „extensions_override_freepbx.conf“ arbeiten, da es sich um einen benutzerdefinierten Typ handelt.
Stellen wir zunächst sicher, dass die Datei „extensions_override_freepbx.conf“ in der Datei „/etc/asterisk/extensions.conf“ enthalten ist. Führen Sie dazu den 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 bringen Sie sie in die folgende 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,)
#####################Wie ich bereits geschrieben habe, ist das „&“-Symbol am Ende erforderlich. Da wir in einem Bash-Skript mit CDR-Daten direkt aus der MySQL-Datenbank arbeiten und diese Daten erst nach der Ausführung von „exten => h,2,Macro(hangupcall,)“ in MySQL eingegeben werden, müssen wir nicht darauf warten Bash-Skript, um die Verarbeitung abzuschließen, und fahren Sie mit dem nächsten Schritt in Asterisk fort. Und das Bash-Skript selbst muss eine Zeitverzögerung enthalten, bevor sein Hauptteil ausgeführt wird.
Damit Änderungen in der Konfigurationsdatei „/etc/asterisk/extensions_override_freepbx.conf“ wirksam werden, müssen Sie den Asterisk-Kernel mit dem folgenden Befehl neu starten:
/usr/sbin/asterisk -rx "core restart now"Dies muss erfolgen, nachdem das Bash-Skript erstellt wurde.
Fazit
Dies ist wahrscheinlich die 1001. Möglichkeit, in Asterisk „entgangene Anrufe abzufangen“. Teilen Sie in den Kommentaren mit, wie Sie dieses Problem lösen. Und was kann Ihrer Meinung nach verbessert/neu gemacht/optimiert werden. Für konstruktive Ideen sind wir dankbar.
Source: habr.com
