Callback / Callthrough, bessere Methode gesucht

hardy88

Neuer User
Mitglied seit
22 Aug 2008
Beiträge
116
Punkte für Reaktionen
0
Punkte
16
Hallo Experten,
ich möchte eine CallBack-Funktion über CAPI einrichten. Wenn eine bestimmte MSN angerufen wird, soll die TK-Anlage den Ruf an Asterisk 1.4 über den internen Bus leiten. Asterisk soll auflegen und nach 10s den Anrufer zurückrufen. Ich scheiter leider daran, dass Asterisk beim Erreichen des Dial-Kommandos einfach ohne Fehlermeldung auflegt. Hier der Auszug aus der extensins.conf:

[isdn-in]
exten => 12,1,Goto(callback,{EXTEN},1)

[callback]
exten => _X.,1,SoftHangup(CAPI/ISDN1)
exten => _X.,2,Wait(10)
exten => _X.,3,Dial(CAPI/ISDN1(14:${CALLERID(num)},60,G(callback^i^2)
exten => i,1,NoOp()
exten => i,2,NoOp()
exten => Goto(callthrough,s,2)

[callthrough]
.....

Falls die Zeit von 10s zu kurz ist, habe ich sofort nach der Rufsignalisierung von Hand beim anrufenden Handy aufgelegt. Leider kommt dann kein Rückruf.
Asterisk zeigt folgendes, wenn der Dial-Befehl drann ist. Alles wird sofort, ohne Pause ausgegeben:

-- Executing [12@callback:3] Dial("CAPI/ISDN1#02/12-0", "CAPI/ISDN1/14:017xxxxxxxxx|60|G(callback^i^2)") in new stack
-- Called ISDN1/14:017xxxxxxxxx
== ISDN1#01: CAPI Hangingup for PLCI=0x201 in state 5
== Spawn extension (callback, 12, 3) exited non-zero on 'CAPI/ISDN1#02/12-0'
== ISDN1#02: CAPI Hangingup for PLCI=0xdead0000 in state 4

Ich habe in meiner Verzweiflung schon sehr viel ausprobiert. Einmal hat es sogar schon funktioniert. Als ich dann meiner Meinung nach überflüssiges Zeug (eigentlich nur Kommentar) löschte, ging es nicht mehr.

Hat jemand mit CallBack Erfahrung? Ich wollte eigentlich eine übersichtliche Lösung, die ohne externe Skripts auskommt. Hat Asterisk 1.4 hier eventuell ein Bug?

Vielen Dank für's Mitdenken.
 
Zuletzt bearbeitet:
Hat jemand mit CallBack Erfahrung? Ich wollte eigentlich eine übersichtliche Lösung, die ohne externe Skripts auskommt.

Auf meinem Asterisk 1.6 verwende ich sowohl Callback als auch callthrough. Hier der Teil der extensions.conf (muss vielleicht minimal auf * 1.4 angepasst werden):
Code:
[incoming]
exten => 000387dusnet,1,Goto(callback&callthrough,cbct,1)	;callback & Callthrough, wenn auf dieser MSN ein Anruf eingeht


[callback&callthrough]
exten => cbct,1,ExecIf($[${DB_EXISTS(callback&callthrough/${CALLERID(num)})}]?MSet(NUMMER=${CUT(DB(callback&callthrough/${CALLERID(num)}),.,1)},CALLTO=X${CUT(DB(callback&callthrough/${CALLERID(num)}),.,2)}):MSet(NUMMER=${CALLERID(num)},CALLTO=PIN))
exten => cbct,2,GotoIf($[${NUMMER}=callthrough]?s,2)
exten => cbct,3,system(echo -e "Channel: Local/${NUMMER}@default\\nCallerid: callback\\nContext: callback&callthrough\\nExtension: s\\nMaxRetries: 2\\nRetryTime: 9\\nSetvar: CALLTO=${CALLTO}" > /var/spool/asterisk/${NUMMER})
exten => cbct,n,system(touch -t ${STRFTIME($[${EPOCH}+6],,%Y%m%d%H%M.%S)} /var/spool/asterisk/${NUMMER})
exten => cbct,n,ExecIf($[${NUMMER:0:1}=0]?system(mv /var/spool/asterisk/${NUMMER} /var/spool/asterisk/outgoing/):system(rm /var/spool/asterisk/${NUMMER}))
exten => cbct,n,ExecIf($[${CALLTO}=PIN]?system(echo `date` '${CALLERID(num)}' >> /root/cbtest):ExecIf($[X${VERM}=XY]?Playback(pbx-transfer):Busy))
exten => cbct,n,Hangup

exten => s,1,ExecIf($[${CALLTO}=PIN]?Authenticate(1234,,4))
exten => s,2,ExecIf($[${CALLTO:1:1}X=0X]?Playback(silence/1&vm-dialout):Playback(silence/0))
exten => s,3,GotoIf($[${CALLTO:1:1}X=0X]?default,${CALLTO:1},1)
exten => s,n,DISA(no-password,default,,,)
exten => s,n,Hangup

Mit entsprechenden Datenbankeinträgen funktioniert das wunderbar. Einfach in der Asterisk-CLI "database put callback&callthrough 01787654321 01787654321..bezeichnung" eingeben. Hier ein paar Beispieldatenbankeinträge (kann man sich mit "database show callback&callthrough" anschauen):
Code:
/callback&callthrough/0179xxxxxxx                 : callthrough..Wasilij           ;=callthrough, wenn von der Nummer angerufen wird
/callback&callthrough/0172xxxxxxx                 : 0172xxxxxxx..Martino           ;=callback erfolgt auf die Nummer 0172xxxxxx, wenn von 0172xxxxxx ein anruf kommt
/callback&callthrough/0176xxxxxxx                 : 04103xxxxxxx..Alex             ;=callback erfolgt auf die Nummer 04103xxxxx, wenn von 0176xxxxx ein Anruf kommt
/callback&callthrough/007902xxxxxxx               : 007902xxxxxxx.0174xxxxxxx.Olga ;=callback erfolgt auf 007902xxxxxx, wenn Anruf von dort kommt, danach wird sofort mit 0174xxxxxx verbunden

Und falls jemand meine Callback-auslösenummer anruft, dessen Nr nicht in dieser AstDB steht, kommt der Callback trotzdem, aber man muss eine PIN (1234) eingeben.
 
Zuletzt bearbeitet:
Hollo PsychoMantis,
hab vielen Dank für Deine Antwort. Es ist zwar eine völlig andere Lösung aber sie sieht sehr vielversprechend aus. Ich hoffe, dass ich's übers WE zum Laufen bekomme. Mit der Datenbank habe ich noch keine Erfahrungen. Bestimmt bringt sie einigen Kompfort. Auf den ersten Blick fällt mir auf, dass keine Dial-Anweisung enthalten ist. Offenbar gibt es größere Unterschiede.
Viele Grüße
hardy88
 
Jetzt konnte ich einige Tests machen. Leider bin ich nicht sehr weit gekommen. Zunächst habe ich herausgefunden, dass ich wohl für die 1.4-er Version die Anweisung MSet durch Set ersetzen muss. Doch leider bekomme ich in der ersten Zeile die Fehlermeldung:

WARNING[15599]: app_exec.c:186 execif_exec: Could not find application! (CALLTO=X):Set(NUMMER=017xxxxxxxxx)
== Spawn extension (callback&callthrough, cbct, 1) exited non-zero on 'CAPI/ISDN1#02/54-0'

Die Datenbank enthällt eine Zeile, entsprechend der 2. Zeile im o.g. Beispiel.

Ich kann leider mit der Fehlermeldung nicht viel anfangen. Kann es sein, dass hier noch etwas fehlt?

Viele Grüße
hardy88
 
Zuletzt bearbeitet:
Kann es sein, dass hier noch etwas fehlt?

Nein, fehlt nichts. Aber wie ich schon sagte, muss man das auf * 1.4 etwas anpassen, da die Schreibweise bei * 1.4 und * 1.6 etwas unterscheidet. Habs mal auf die schnelle auf * 1.4 umgeschrieben. Wenn ich mich nicht verschrieben habe, müsse es so funktionieren:
Code:
[incoming]
exten => 000387dusnet,1,Goto(callback&callthrough,cbct,1)	;callback & Callthrough, wenn auf dieser MSN ein Anruf eingeht


[callback&callthrough]
exten => cbct,1,ExecIf($[${DB_EXISTS(callback&callthrough/${CALLERID(num)})}],Set(NUMMER=${CUT(DB(callback&callthrough/${CALLERID(num)}),.,1)},CALLTO=X${CUT(DB(callback&callthrough/${CALLERID(num)}),.,2)}))
exten => cbct,2,GotoIf($[${DB_EXISTS(callback&callthrough/${CALLERID(num)})}]?4:)
exten => cbct,3,Set(NUMMER=${CALLERID(num)},CALLTO=PIN)
exten => cbct,4,GotoIf($[${NUMMER}=callthrough]?(s,2):)
exten => cbct,3,system(echo -e "Channel: Local/${NUMMER}@default\\nCallerid: callback\\nContext: callback&callthrough\\nExtension: s\\nMaxRetries: 2\\nRetryTime: 9\\nSetvar: CALLTO=${CALLTO}" > /var/spool/asterisk/${NUMMER})
exten => cbct,n,system(touch -t ${STRFTIME($[${EPOCH}+6],,%Y%m%d%H%M.%S)} /var/spool/asterisk/${NUMMER})
exten => cbct,n,ExecIf($[${NUMMER:0:1}=0],system(mv /var/spool/asterisk/${NUMMER} /var/spool/asterisk/outgoing/))
exten => cbct,n,Busy
exten => cbct,n,Hangup

exten => s,1,ExecIf($[${CALLTO}=PIN],Authenticate(1234,,4))
exten => s,2,ExecIf($[${CALLTO:1:1}X=0X],Playback(silence/1&vm-dialout))
exten => s,3,GotoIf($[${CALLTO:1:1}X=0X]?(default,${CALLTO:1},1))
exten => s,n,Playback(silence/0)
exten => s,n,DISA(no-password,default,)
exten => s,n,Hangup
 
Hallo PsychMantis,

Dein Beitrag hat mir sehr geholfen.
Ich habe auch die ExecIf-Anweisungen anpassen müssen. *1.4 kann wohl nur etwas ausführen oder es lassen aber nicht im false-Fall etwas anderes ausführen.

Es funktioniert schon viel. Nun bin ich schon bei dem "Drum herum". Ich denke, dass ich nun weiter komme.

Vielen Dank
hardy88
 
Ich habe auch die ExecIf-Anweisungen anpassen müssen. *1.4 kann wohl nur etwas ausführen oder es lassen aber nicht im false-Fall etwas anderes ausführen.

Jep, ganz genau so ist es. Deshalb nutze ich ja * 1.6. Damit kann man auch mehrere ExecIf-Anweisungen verketten, so dass man komplizierte Sachen bearbeiten kann ala "wenn bedingung1 erfühlt mache A ansonsten wenn bedingung2 erfühlt mache B, wenn bedingung3 erfühlt mache C ansonsten mache D". Bei Asterisk 1.4 geht nur "wenn bedingung1 erfühlt mache A" und das ist schon ziemlich wenig.

Was funktioniert noch nicht?
Post hier einfach was deine CLI sagt, dann können wir hier helfen (in der CLI vorher "set verbose 3" eingeben).
 
Das was noch nicht richtig geht, hat wohl mit dem GSM zu tun. Wenn ich mit einem GSM-Telefon um einen Rückruf "bitte" legt Asterisk so schnell auf, dass man kein Freizeichen hört. Das Telefon schweigt einfach sehr lange. Es erklingt dann erst nach einer sehr langen Zeit, dass die gerufene Nr. z.Z. nicht erreicht werden kann. Inzwischen hat Asterisk schon den zweiten Rückrufversuch gestartet. Ich habe 10s Wartezeit zwischen den Versuchen eingestellt. Nun habe ich versucht vor dem Verschieben der Rückrufdatei ein Wait(10)+SoftHangup(CAPI/ISDN1)+Wait(10) einzufügen. Hier ist wohl ein Bug in Asterisk. Mit dem "Wait (10)" kommt er wohl nicht zurecht. Es wird aufgelegt und der gesamte Ablauf ist unterbrochen. Ich hatte bei den Versuchen mit "Wait" auch schon andere nicht zu erklährende Effekte.
hardy88
 
Zuletzt bearbeitet:
Du willst die Zeit vergrößern? Kein Problem. Ändere einfach die rot markierte Zahl in dieser Zeile:
Code:
exten => cbct,n,system(touch -t ${STRFTIME($[${EPOCH}+[color=red]6[/color]],,%Y%m%d%H%M.%S)} /var/spool/asterisk/${NUMMER})
Standardmäßig habe ich auf 6 Sekunden eingestellt. Mach einfach mehr daraus.
 
Ja, das ist eine Möglichkeit für die Zeit zw. Auflegen und Rückruf.

Ich suchte nach einer Möglichkeit die Zeit zw. dem Anruf und der Rufabweisung zu verlängern. Schade, dass das mit dem Wait nicht einfach funktioniert.

Viele Grüße
hardy88
 
Ich wollte erreichen, dass beim Anruf auf die MSN zur Rückrufanforderung nicht einfach nur nichts im Hörer zu hören ist. Ich wollte, dass zunächst wenigstens einmal ein Freizeichen zu hören ist und dann, wenn Asterisk aufgelegt hat, das Besetztzeichen.

Wenn ich ein Wait(10) anstelle von Busy einfüge funktioniert es manchmal. Vielleicht ist das ja auch ein Problem des GSM.

Ich habe noch mehr vor. Hast Du eine eine Idee, wie ich abfragen kann, mit welcher Dienstekennung (Sprache, Fax, Daten,...) ein Anruf herein kommt?

Hast Du eine Idee, wie ich bei Anrufen ohne Absender-MSN unterscheiden kann, ob der Anrufer die Übertragung der MSN absichtlich unterdrückt hat oder ob der Netzanbieter dieses Dienstmerkmal beim Anrufer nicht freigeschaltet hat? Als ich das früher mal unter Windows mit Java implementiert habe war das möglich. Kann Asterisk das auch?

Viele Grüße
hardy88
 
Hi,
ich möchte den "alten" Thread mal aufleben lassen weil die Problematik immer aktuell ist ;)
Ich versuche den Callthrough-Code gerade zu verstehen, finde aber 1. irgendein Dial-Kommando nicht darin und 2. wird in der "exten => s,3, " auf default verwiesen. Auch habe ich 3. nicht gefunden wie asterisk auf die einzugebene Nummer per DTMF wartet um per callthrough weiterzuleiten.
Kannst du hier aufklären?
Btw: wozu die Dateien in /var/spool/asterisk?
 
Ohne die Funktionsweise von callback näher zu erklären, nehme ich mal an, dass du lieber callthrough nutzen willst, da es einfacher und komfotabler ist (callthrough geht vom Telefonbuch des Handys - callback dagegen nicht).
Und dazu ist der Dialplan ziemlich einfach:
Code:
s =>{	NoOp(${CALLERID(all)}); if (${DB_EXISTS(callthrough/${CALLERID(num)})}) 
{ Progress; MSet(TIMEOUT(response)=60,TIMEOUT(digit)=10); DISA(no-password,default,,,a); Busy; }}
Wenn also ein Anruf auf der extension s eingeht und die CallerID des Anrufers in der AstDB ist, dann bekommt man sofort den Freiton zu hören.
 
Zuletzt bearbeitet:
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.