Open Source im professionellen Einsatz
Linux-Magazin 02/2008
© hulibu, photocase.com

© hulibu, photocase.com

Workshop: Die eigene Asterisk-Anlage - Teil 2

Erweiterte Gesprächskultur

Im zweiten Teil des großen Telefonanlagen-Workshops erfahren Sie, wie Sie komplexe Komfortfunktionen programmieren, beispielsweise interaktive Sprachmenüs, und welche Mechanismen Asterisk im Einzelnen dafür in seinem Ärmel hat.

1368

Im ersten Teil der Artikelserie [1] haben Sie gelernt Asterisk [2] zu installieren und so zu konfigurieren, dass Sie intern und extern über einen SIP-Provider telefonieren können. In dieser Folge bekommen Sie das Handwerkszeug, um dieser noch recht einfachen Telefonanlage Komplexität und Intelligenz einzuhauchen. Los geht\'s mit dem Interactive Voice Response System.

Das IVR stellt Automaten bereit, die den Anrufer anhand von Sprachmenüs führen und weiterverbinden - also ungleich mehr als ein Anrufbeantworter (Abbildung 3). Um eine IVR aufzubauen, müssen Sie natürlich zuvor Sprachdateien aufnehmen. In Asterisks Köcher steckt dafür die Applikation »Record()«. Im Gegensatz zu »Playback()« verlangt »Record()«, dass die Endung des übergebenen Dateinamens zu dem gewünschten Codec passt.

Mit dem Dialplan in Listing 1 können Sie durch Anrufen der 9900 bis 9999 unkompliziert 100 verschiedene Sprachdateien - auch Sprach- oder Voiceprompts genannt - aufnehmen. Sie beenden jede Aufnahme durch Auflegen, die [#]-Taste oder durch Warten. Eine lange Pause am Ende eines Sprachprompts macht sich jedoch schlecht beim Aneinanderketten von mehreren Prompts.

Listing 1:
»extensions.conf« (1)

01 exten => _99XX,1,Answer()
02 exten => _99XX,2,Wait(1)
03 exten => _99XX,3,Record(/tmp/sprachprompt${EXTEN:2}.wav)
04 exten => _99XX,4,Wait(1)
05 exten => _99XX,5,Playback(/tmp/sprachprompt${EXTEN:2})
06 exten => _99XX,6,Hangup()

Um mit den Sprachprompts ein IVR zu realisieren, benutzen Sie die Applikation »Background(Dateinamen)«. Sie spielt den angegebenen Voiceprompt vor und gibt DTMF-Eingaben während des Abspielens an den Dialplan weiter. Der verarbeitet die Touchtones wie ganz normale Anrufe. Wenn Sie während eines Background die [8][8] eingeben, dann sucht Asterisk im aktuellen Context nach der Extension 88 und arbeitet ihn von der Priorität 1 beginnend ab.

Eine einfache Übung: Besprechen Sie die folgenden Voiceprompts und speichern Sie sie danach im Verzeichnis »/var/lib/asterisk/sounds/« ab:

  • »eingabe.wav«: "Bitte drücken Sie auf
    Ihrer Telefontastatur eine Zahl."
  • »gerade.wav«: "Diese Zahl ist
    gerade."
  • »ungerade.wav«: "Diese Zahl ist
    ungerade."

Mit dem Dialplan aus Listing 2 probieren Sie die IVR-Funktion aus. Achtung: Die Eingabe muss während der Abarbeitung von »Background()« passieren! Wollen Sie dem User eine Möglichkeit geben, weitere Eingaben zu machen, benutzen Sie die vorgefertigten Asterisk-Prompts »silence/1« bis »silence/9«:

exten => 30,1,Answer()
exten => 30,n,Background(eingabe)
exten => 30,n,Background(silence/5)
exten => 30,n,Hangup()

Die Zahlen stehen für die Anzahl der Sekunden, in der Asterisk Stille abspielt.

Listing 2:
»extensions.conf« (2)

01 exten => 30,1,Answer()
02 exten => 30,n,Background(eingabe)
03 exten => 30,n,Hangup()
04 
05 exten => _[13579],1,Playback(ungerade)
06 exten => _[13579],n,Hangup()
07 
08 exten => _[2468],1,Playback(gerade)
09 exten => _[2468],n,Hangup()

Mehrstufige IVRs

Das Problem des gezeigten IVR-Konzepts ist, dass es immer innerhalb eines Context arbeitet und deshalb mehrstufige IVRs nur über mehrstellige Ziffern abbilden kann (Abbildung 1 und passendes Listing 3). Das ist natürlich unbefriedigend, aber ein mit der Applikation »Goto()« lösbares Problem. Goto springt wie im guten alten Basic an eine beliebige Stelle des Programms.

Listing 3:
»extensions.conf« (3)

01 [ivr]
02 exten => 50,1,Answer()
03 exten => 50,n,Background(beispielmenue)
04 exten => 50,n,Background(silence/5)
05 exten => 50,n,Hangup()
06 
07 ; Da in einem Context eine Extension nur
08 ; einmal vorhanden sein kann, realisiert
09 ; das Beispiel die Menueebenen durch
10 ; fortlaufende (auch zweistellige) Zahlen
11 ;
12 exten => 1,1,Background(dummy1)
13 exten => 1,n,Background(silcence/5)
14 exten => 1,n,Hangup()
15 
16 exten => 2,1,Playback(dummy2)
17 exten => 2,n,Hangup()
18 
19 exten => 3,1,Playback(dummy3)
20 exten => 3,n,Hangup()
21 
22 exten => 4,1,Playback(dummy4)
23 exten => 4,n,Hangup()

In Asterisk hüpft ein »Goto(10)« zur Priorität 10 in der aktuellen Extension. »Goto(555,1)« geht zur Extension 555 und da zur Priorität 1. Spannend ist »Goto(produktion,20,5)«, das im Context »produktion« die Extension 20 und Priorität 5 anspringt. Mit diesem Trick können Sie bei der Eingabe einer einstelligen Zahl auf der Menü-Ebene 1 auf eine zweistellige Extension in einem anderen Context verzweigen und haben dort wieder die einstelligen Zahlen von 0 bis 9 als Eingabeoption zur Verfügung (Abbildung 2 und zugehöriges Listing 4).

Listing 4:
»extensions.conf« (4)

01 [ebene0]
02 exten => 50,1,Answer()
03 exten => 50,n,Background(beispielmenue)
04 exten => 50,n,Background(silence/5)
05 exten => 50,n,Hangup()
06 
07 ; Um in der naechsten Ebene die einstelligen
08 ; Zahlen fuer Eingaben frei zu halten, sollte
09 ; man an eine beliebige mehrstellige Extension
10 ; springen.
11 ;
12 exten => 1,1,Goto(ebene1,99,1)
13 
14 exten => 2,1,Playback(dummy2)
15 exten => 2,n,Hangup()
16 
17 [ebene1]
18 exten => 99,1,Background(dummy1)
19 exten => 99,n,Background(silcence/5)
20 exten => 99,n,Hangup()
21 
22 exten => 1,1,Playback(dummy3)
23 exten => 1,n,Hangup()
24 
25 exten => 2,1,Playback(dummy4)
26 exten => 2,n,Hangup()

Wer die »n«-Priorität benutzt, muss für Goto Sprungadressen-Labels definieren. Das Beispiel

exten => 40,1,Answer()
exten => 40,n(anfang),Playback(hello-world)
exten => 40,n,Wait(0.5)
exten => 40,n,Goto(anfang)

zeigt, dass Asterisk die Labelnamen-Definition in Klammern nach dem »n« in der Extension erwartet.

Jedes IVR sollte Falscheingaben abfangen und den User wieder auf ein Grundmenü bringen. Eine nicht definierte Eingabe fangen Sie mit der »i«-Extension ab. Im Gerade/ungerade-Beispiel behandelt die Zeile

exten => i,1,Goto(30,2)

die Eingabe der Null und bringt den User wieder ins Grundmenü.

Abbildung 1: Asterisks IVR-Konzept arbeitet nur innerhalb eines Context (siehe Listing 3).

Abbildung 2: Dank Goto verzweigt Listing 4 bei der Eingabe einer Ziffer auf der Menü-Ebene 1 auf eine zweistellige Extension in einem anderen Context.

Verzweigungen im Dialplan

Als essenzielles Programmier-Element fehlt noch eine Möglichkeit, in Dialplänen bedingungsgesteuert zu verzweigen. Dies geht mit der Applikation »GotoIf()«. Die zugehörige Bedingung erwartet Asterisk als Expression in eckigen Klammern mit einem vorgestellten Dollarzeichen. Die Asterisk-Community bemüht als Beispiel für eine »GotoIf()«-Anwendung gern das Exfreundin-Szenario:

exten => 1234,1,GotoIf($[${CALLERID(num)} = 03012345678]?10:20)
exten => 1234,10,VoiceMail(1234,u)
exten => 1234,20,Dial(SIP/1234)

Wenn der Anruf von der Rufnummer 03012345678 kommt, verbindet ihn das System direkt mit der Voicemailbox 1234. Ansonsten stellt es das Gespräch ganz normal an das Telefon 1234 durch.

Eine Auflistung aller Applikationen bekommen Sie im CLI mit »core show applications«. Hilfe zu einer bestimmten Applikation gibt\'s mit »core show application Application-Name« (siehe Auszug in Listing 5). Eine deutschsprachige Beschreibung aller Applikationen finden Sie online unter [3].

Listing 5: »*CLI> core
show application VoiceMail«

01 -= Info about application 'VoiceMail' =-
02 
03 [Synopsis]
04 Leave a Voicemail message
05 
06 [Description] VoiceMail(mailbox[@context][&mailbox[@context]][...][|options]): This application allows


the calling party to leave a message for the specified list of mailboxes. When multiple mailboxes are


specified, the greeting will be taken from the first mailbox specified. Dialplan execution will stop


if the specified mailbox does not exist.
07 
08 The Voicemail application will exit if any of the following DTMF digits are received:
09     0 - Jump to the 'o' extension in the current dialplan context.
10     * - Jump to the 'a' extension in the current dialplan context.
11 [...]

Die am häufigsten verwendete Variable in Dialplänen ist »${EXTEN}«. Sie gibt die gewählte Extension, also das Ziel des Anrufs aus. Da Asterisk weder über einen Debugger noch über sonstige Programmiertools verfügt, muss zum Anzeigen von Variablen die Applikation »NoOp()« herhalten. Diese No Operation listet den Inhalt der Klammer ab einem Verbose-Level von 3 (einstellbar mit »core set verbose 3«) im CLI auf. Zum Beispiel:

exten => _XXX,1,Answer()
exten => _XXX,n,NoOp(Anruf fuer ${EXTEN})
exten => _XXX,n,Playback(hello-world)
exten => _XXX,n,Hangup()

Systemvariablen wie »${EXTEN}« lassen sich nur lesen, selbst definierte Variablen lesen und schreiben. Fürs Schreiben zeichnet die Funktion Set() verantwortlich, deren Syntax lautet »Set(VARIABLENNAME=Wert[,Option])«.

Asterisk kennt zwei Arten von Variablen: Channel und globale. Channel-Variablen gelten immer nur im aktuellen Gespräch und sind außerhalb des Gesprächs nicht für andere Gespräche (Channels) nutzbar. Hingegen dürfen der gesamte Dialplan und alle Channel globale Variablen übergreifend setzen und lesen. Eine globale Variable lässt sich mit der Option »,g« in der »Set()«-Funktion bearbeiten. Ohne »,g« geht Asterisk immer von Channel-Variablen aus. Das Beispiel

[globals]
ANZAHL=0
[meine-telefone]
exten => 1234,1,Set(ANZAHL=$[${ANZAHL} + 1])
exten => 1234,n,Answer()
exten => 1234,n,SayNumber(${ANZAHL})
exten => 1234,n,Hangup()

zählt die Anzahl der Gespräch seit Systemstart und spielt sie dem Anrufer mit der Applikation »SayNumber()« vor. Sie setzen eine globale Variable normalerweise beim Starten von Asterisk und auch bei jedem Reload neu. Das kann in der »extensions.conf« im Bereich »[globals]« erfolgen wie oben im Beispiel.

Abbildung 3: Der sprechende Urvater, das Alibiphon der Firma Willy Müller aus dem Jahr 1957, spielte dem Anrufer einen aufgezeichneten Text vor, beispielsweise die Geschäftsöffnungszeiten. Mit Asterisk und einem Linux-PC kann heute jedermann ein Interactive Voice Response System konfigurieren.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 6 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Zeit für was Neues

    Der eine braucht sowieso gerade eine neue, den anderen nervt, dass sich der Vermieter seiner Telefonanlage jedes Komfortmerkmal extra bezahlen lässt. Zeit zu wechseln, Zeit eine VoIP-fähige Anlage selbst zu bauen, Zeit für einen Asterisk-Workshop im Linux-Magazin.

  • Gemeinschaft an der Strippe

    Asterisk-Toolkits wie das auf deutsche Verhältnisse angepasste Projekt mit dem schönen Namen Gemeinschaft helfen den Admins und Systemintegratoren, eine Telefonanlage ab mittlerer Größe mit überschaubarem Aufwand zu migrieren und zu betreiben.

  • Geglückte Verbindung?

    Seit wenigen Wochen gibt es ein Skype-Plugin für den freien Telefonie-Server Asterisk. Mitarbeiter der TU Wien haben die Vernunftehe fürs Linux-Magazin getestet.

  • Ruf mich an!

    Alles, was über Telefonie hinausgeht, macht den wirklichen Mehrwert von Asterisk aus: Sprachportale beispielsweise, die Fluggäste identifizieren und informieren, bei einer frostigen Wohnung warnen oder den Admin mimen, wenn die User ihre Passwörter verschusselt haben.

  • Ein Stern am Telefonhimmel

    Asterisk erschließt kleinen und größeren Firmen kostengünstig die Welt der IP-Telefonie. Die Vermittlungsstelle aus Open-Source-Software verbindet Computer, interne Hardware-IP-Telefone und Voice-Mailbox mit dem Fest- und Mobilfunknetz. Somit lässt sich einfach ein VoIP-Gateway für ein Büro-LAN aufziehen.

comments powered by Disqus

Ausgabe 08/2016

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.