In meinem vorherigen Beitrag ging es um Anrufsignalisierung auf einem Trunk der Telefonanlage, die keine Zielrufnummer mitliefert. Im Beispiel kam ein Sipgate Basic Trunk zu Einsatz. Bei diesem Anbieter gibt es sogar zwei Telefonnummern gratis – aber nur einen Zugang. Damit ist meine Lösung obsolet.
Es gibt aber andere Anbieter, die mehrere Nummern gratis anbieten und auch mehrere Zugänge erlauben. Zum Beispiel Fonial. Es bietet erstaunlich viele Möglichkeiten schon auf deren Server. Anrufbeantworter, Spamfilter, einfache Weiterleitungsregelt – es ist schon einiges und viele werden sicher damit schon glücklich. Ich nutze die Nummern mit einer 1:1 Umsetzung auf die Zugänge, die ich mir parallel dazu geschaffen habe. Und so sieht es (pseudonymisiert) bei mir aus:
from-trunk-fonial-A, from-trunk-fonial-B und from-trunk-fonial-C sind die drei Kontexte für die drei Trunks, immer jeweils in „pjsip settings“ hinterlegt. Dann gibt es die drei „Werkbänke“: ContextFoA, ContextFoB und ContextFoC. Dabei entspricht A immer der Nummer 0123000003 , B der Nummer 0123000004 und C der Nummer 0123000005. Aus dem SIP-Header kann Asterisk die Extension heraus lesen. Leider ist es nicht die „Durchwahl“ sondern der Benutzername. Der Trick besteht also darin, im Dialplan (so nennt man grob den Ablauf in einem Kontext) die Variable EXTEN zu untersuchen und dann zu entscheiden, wohin es gelenkt werden soll. (Es kann mein Versehen sein aber ich habe es mehr als einmal gesehen, dass ein Anruf über den falschen Trunk kam und deshalb verlasse ich mich ausschließlich auf den Benutzernamen!) Fangen wir an!
[from-trunk-fonial-A]
exten => _.,1,NoOp(${CONTEXT} -> ${EXTEN})
same => n,GotoIf($[${EXTEN} = foA]?ContextFoA:ContextFoB)
same => n(ContextFoA),Goto(ContextFoA,0123000003,1)
same => n(ContextFoB_ContextFoC),GotoIf($[${EXTEN} = foB]?ContextFoB:ContextFoC)
same => n(ContextFoB),Goto(ContextFoB,0123000004,1)
same => n(ContextFoC),Goto(ContextFoC,0123000005,1)
Mein erster Trunk loggt als Erstes das Ereignis und das Umfeld. Dann geht es ans Eingemachte: mit einem GotoIf lasse ich den „Anruf“ (eigentlich Channel) zu einer weiteren benannten Zeile springen. Deshalb haben die Zeilen nicht nur die fortlaufende Nummer „n„, sondern auch einen Namen, der in Klammern dahinter steht. Als erste Abfrage wird geschaut: ist die Durchwahl gleich dem Benutzernamen „foA„. Wenn ja (nach dem „?„) springe ich zur Zeile ContextFoA, die den Anruf in den Kontext ContextFoA mit der Nummer 0123000003 als erstem Argument schickt und zwar ab Zeile „1“. Ansonsten (nach „:“) soll in ContextFoB_ContextFoC entschieden werden, ob es über ContextFoB-Zeile in den Kontext ContextFoB oder über die Zeile ContextFoC in den Kontext ContextFoC geschickt werden soll.
Aber was passiert in dem mysteriösen Kontext?
[ContextFoA]
exten => _.,1,NoOp(${CONTEXT} -> ${EXTEN} )
same => n,Set(__DID=0123000003)
same => n,NoOp(${CONTEXT} -> ${EXTEN} -> ${DID} as defined in ContextFoA extensions_custom.conf)
same => n,Answer()
same => n(dest-ext),Goto(from-pstn,0123000003,1)
Am Anfang kurz zu Protokoll geben, dass was Neues anfängt (die erste Zeile im Dialplan muss als solche erkennbar sein: Durchwahl,1,Anwendung -> „exten => _.,1,NoOp…“ und danach kann allem fortlaufend mit „same => n,“ als Fortsetzung angegeben werden). Ein „_.“ passt dabei auf alles, was eine Rufnummer sein kann.
Die DID wird für mögliche spätere Verwendung gespeichert, danach (eigentlich überflüssig) Log-Eintrag, um zu erkennen wo der Ablauf definiert wurde. Es folgt, wie früher auch, Übernahme des Anrufs und die Weiterleitung zu „from-pstn„, wo man kein weiteres „-toheader“ braucht, weil die EXTEN-Variable schon befüllt ist und die inbound routes erkennen können, was zu tun ist.
Für die anderen Trunks und Kontexte gilt analog dasselbe und ich bin mir nicht sicher, ob man das nicht noch mehr zusammen fassen könnte oder Duplizierung des Codes verzichten könnte. Ja, man kann sogar ohne Kontext-Wechsel direkt zur inbound route der DID springen. Dazu lassen wir die 3 Trunks in den Kontext from-trunk-fonial (also ohne -A, -B und -C) gehen. Die Zeile ContextFoA, ContextFoB oder ContextFoC stellt direkt zu ‚from-pstn‘ durch. Bei mir gab es aber Probleme mit Erkennung des Anrufers aus der Kontaktdatenbank (sieht nach einem Fehler von FreePBX Dialplan aus) und weil ich weiß, wohin der Anruf soll, schreibe ich es mir noch kürzer und überspringe dabei die Konfiguration des Channels:
[from-trunk-fonial]
exten => _.,1,NoOp(${CONTEXT} -> ${EXTEN})
same => n,GotoIf($[${EXTEN} = foB]?ContextFoB:ContextFoA_ContextFoC)
same => n(ContextFoB),Goto(from-pstn,0123000004,1)
same => n(ContextFoA_ContextFoC),GotoIf($[${EXTEN} = foA]?ContextFoA:ContextFoC)
same => n(ContextFoA),Goto(from-pstn,0123000003,did-cid-hook)
same => n(ContextFoC),Goto(from-pstn,0123000005,did-cid-hook)
Damit kann man auch mehr als drei Trunks abdecken. Aber will man wirklich so komplizierte GotoIf-Abfragen bauen? Gerne lasse ich mir erklären, wie man es noch einfacher machen könnte! Kommentare also vollkommen willkommen!