In diesem Abschnitt werde ich Ihnen Schritt für Schritt zeigen, wie Sie Ihr eigenes Incoming-Skript schreiben können. Wir fangen an, indem wir einfach jeden eingehenden Anruf annehmen und einen Piep abspielen. Das letzte Beispiel ist ein sehr einfacher, aber nützlicher Anrufbeantworter mit Fax-Erkennung und -Empfang.
Lassen Sie uns mit einem sehr einfachen Fall anfangen: wir nehmen alle eingehenden Anrufe an, piepen und nehmen etwas auf, sodass wir eine Audio-Datei haben, mir der wir später ein bisschen rumspielen können. Legen Sie zuerst irgendwo ein neues Verzeichnis an, für das root Schreibrechte haben muss. Wir brauchen auch eine Test-Audio-Datei, um sie zu verschicken. Lassen Sie uns den Piep nehmen, der mit CapiSuite geliefert wird.
mkdir capisuite-examples chmod 777 capisuite-examples # schreibbar für alle cd capisuite-examples cp /usr/local/share/capisuite/beep.la .
Vielleicht müssen Sie den Pfad in der letzten Zeile anpassen, damit er zu Ihrer Installation passt.
Kopieren Sie das hier gezeigte Beispiel jetzt in eine Datei namens example.py in diesem Verzeichnis. Vergessen Sie nicht, den Pfad my_path zu ändern.
Beispiel 2.1. example.py
import capisuitemy_path="/path/to/the/just/created/capisuite-examples/"
def callIncoming(call,service,call_from,call_to):
capisuite.connect_voice(call,10)
capisuite.audio_send(call,my_path+"beep.la")
capisuite.audio_receive(call,my_path+"recorded.la",20,3)
capisuite.disconnect(call)
Lassen Sie uns das Skript Zeile für Zeile durchgehen:
![]() | Das capisuite-Modul, das alle CapiSuite-spezifischen Funktionen enthält, wird importiert. Alle CapiSuite-Objekte (Funktionen, Konstanten) in diesem Modul können nun über capisuite.objectname angesprochen werden. Sie können auch ein "from capisuite import *" machen, das alle Objekte in den aktuellen Namespace einfügt - aber dies wird nicht empfohlen, da sie mit anderen globalen Objekten kollidieren können. AnmerkungDas importierte Modul capisuite ist nicht als extra Modul verfügbar, sodass Sie dies nicht in einer interaktiven Python-Session tun können. Es wird in das CapiSuite-Binary eingebunden und ist nur in Skripten, die von CapiSuite interpretiert werden, verfügbar. |
![]() | ändern Sie dies bitte auf den echten Pfad, aus dem Sie diese Beispiele aufrufen. |
![]() | Defininieren Sie die erforderliche Funktion wie im „Das Incoming-Skript“ beschrieben. |
![]() | Dies ist die erste CapiSuite-Funktion, die wir verwenden: Sie nimmt den wartenden Anruf an. Der erste Parameter teilt CapiSuite mit, welchen Anruf Sie meinen. Dieser Parameter ist für fast alle CapiSuite-Funktionen erforderlich. Ok, wir haben jetzt nur einen Anruf - aber stellen Sie sich ein Incoming-Skript vor, das zur selben Zeit auch noch einen ausgehenden Anruf tätigen will (zum Beispiel, um einen Anruf weiterzuleiten). In diesem Fall wüßte CapiSuite, welchen Anruf Sie meinen - deshalb müssen Sie die übergebene Referenz an alle Funktionen weiterreichen, die mit der Verbindung zu tun haben. Sie können CapiSuite auch sagen, dass es eine bestimmte Zeit warten soll, bevor es einen Anruf annehmen soll - dafür wird der zweite Parameter benutzt. Diese Skript wartet also 10 Sekunden bevor die Verbindung zum Anrufer hergestellt wird. Glauben Sie nicht, dass dieser Paramter überflüssig ist und dass Sie stattdessen eine Python-Funktion (z.B. time.sleep()) aufrufen können, um zu warten. Dies wird für Verzögerungen länger als 4 (oder 8, hängt von Ihrem ISDN-Setup ab) Sekunden nicht funktionieren, da der Anruf abgewiesen wird, wenn er nicht von einem ISDN-Device "vor-angenommen" wird, indem Ihrem Netz-Provider mitgeteilt wird, dass es klingelt. CapiSuite macht das, wenn nötig - nutzen Sie also bitte diesen Parameter. |
![]() | Dieser Aufruf sollte ziemlich selbsterklärend sein. Er sendet die Audio-Datei, die unter beep.la gespeichert ist. |
![]() | Nimmt eine Audio-Datei von maximal 20 Sekunden auf - es wird eher aufgehört, wenn mehr als 3 Sekunden Stille erkannt werden. |
![]() | Last, but not least - wird die Verbindung beendet. Auflegen. Fertig. Es ist vorbei. |
Die CapiSuite-Konfiguration muss geändert werden, um das gerade erstellte Skript nutzen zu können. Editieren Sie dazu Ihre capisuite.conf und ersetzen Sie den incoming_script-Wert durch den Pfad zur Datei, die Sie gerade erstellt haben (siehe „Konfiguration von CapiSuite“) und starten Sie CapiSuite neu.
Probieren Sie's mal aus: Rufen Sie irgendeine Nummer Ihrer ISDN-Karte an - wenn sie am ISDN-Anschluss hängt, geht jede Nummer (MSN) - wenn sie an einer Telefonanlage hängt, müssen Sie eine Nummer wählen, die in der Anlage für die Karte konfiguriert ist.
Sie sollten einen Piep hören und dann können Sie etwas auf diesen primitiven Anrufbeantworter sprechen. Legen Sie bitte nicht auf, bevor das Skript dies macht, da dieser Fall noch nicht behandelt wird. Warten Sie einfach 3 Sekunden, nachdem Sie etwas gesagt haben - es sollte die Verbindung nach dieser Stille-Periode trennen.
Wenn das nicht funktioniert, haben Sie vielleicht einen Fehler beim Kopieren des Skripts gemacht. In diesem Fall können Sie sich das Log und Error-Log von CapiSuite anschauen. Sie finden dies unter /var/log/capisuite oder /usr/local/var/log/capisuite, wenn Sie den Pfad nicht geändert haben.
Ein guter Trick, um auf Syntaxfehler zu prüfen, ist, Ihre Skripte durch den normalen Python-Interpreter laufen zu lassen. Rufen Sie dazu python /path/to/your/example.py auf. Natürlich wird er sich über das import capisuite beschweren, da dies kein Standard-Python-Modul ist. Aber bevor er dies macht, prüft er die Syntax Ihres Skripts - wenn Sie also irgendeinen anderen Fehler bekommen, beheben Sie ihn und probieren Sie es nochmal. Wenn Sie nur
Traceback (most recent call last): File "../scripts/incoming.py", line 16, in ? import capisuite,cs_helpers ImportError: No module named capisuite
bekommen, hat Ihr Skript die korrekte Syntax.
Ich hoffe, Sie haben Ihr Skript jetzt zum Laufen bekommen - wenn nicht, zögern Sie nicht, auf der CapiSuite-Mailingliste zu fragen, wenn Sie zuvor ein Python-Tutorial gelesen haben.
Im nächsten Abschnitt werden wir eine Ansage verwenden. Nehmen Sie also einge Worte mit diesem einfachen Skript auf und verschieben Sie die erzeugte Datei recorded.la nach announce.la.
Gut, es ist wirklich nicht so schön, dass der Anrufer nicht auflegen darf - und es ist schlecht, dass wir alle eingehenden Anrufe annehmen - dadurch nehmen wir vielleicht der Mutter ihre wichtigen Anrufe weg.
Lassen Sie uns das schnell verbessern.
Beispiel 2.2. example.py, verbessert
import capisuite my_path="/path/to/the/just/created/capisuite-examples/" def callIncoming(call,service,call_from,call_to): try:if (call_to=="123"):
capisuite.connect_voice(call,10) capisuite.audio_send(call,my_path+"announce.la")
capisuite.audio_send(call,my_path+"beep.la") capisuite.audio_receive(call,my_path+"recorded.la",20,3) capisuite.disconnect(call) else: capisuite.reject(call,1)
capisuite.disconnect(call)
except capisuite.CallGoneError: capisuite.disconnect(call)
![]() | CapiSuite sagt dem Skript, dass die Gegenstelle aufgelegt hat, indem die Exception namens CallGoneError ausgelöst wird. Sie sollten deshalb Ihren Code immer in ein try-Statement einfassen und die ausgelöste Exception am Ende Ihres Skripts (oder früher, wenn nötig) behandeln. Diese Exception kann durch ein CapiSuite-Kommando ausgelöst werden. |
![]() | Wir schauen uns die angerufene Nummer an (ersetzen Sie bitte 123 durch die Nummer, die CapiSuite akzeptieren soll)... |
![]() | Die Ansage, die wir im letzten Abschnitt aufgenommen haben, wird abgespielt. Wenn Sie das nicht möchten, nehmen Sie einfach eine neue auf und verschieben Sie die Datei recorded.la wieder nach announce.la. |
![]() | Der Anruf wird ignoriert. Der zweite Parameter teilt den genauen Grund für die Ablehnung mit - Sie können den Anruf ignorieren (jedes andere ISDN-Device oder Telefon klingelt für diese Nummer weiter), indem Sie 1 angeben, aktiv die Verbindung beenden, indem Sie 2 angeben, oder irgend einen Fehler-Code, der in der ISDN-Spezifikation enthalten ist (siehe „ISDN-Fehler-Codes“ für die verfügbaren Codes). |
![]() | Sie müssen immer am Ende Ihres Skripts disconnect aufrufen, da dieses immer auf das Ende des Anrufs wartet, während reject nur die Ablehnung des Anrufs auslöst. Andernfalls erhalten Sie eine Warning im Error-Log. |
![]() | Dies ist der Exception-Handler für CallGoneError - die Exception, die CapiSuite auslöst, wenn der Anruf vom anderen Gespächspartner beendet wird. Sie sollten hier auch disconnect aufrufen, um zu warten bis der Anruf vollständig beendet wurde. |
Speichern Sie dies wieder als example.py und probieren Sie es aus. Es ist nicht erforderlich, CapiSuite neu zu starten, da alle Skripte jedesmal, wenn sie ausgeführt werden, neu gelesen werden. Jetzt dürfen Sie auch auflegen ;-).
Wir haben immer den selben Namen verwendet, um die aufgenommene Nachricht zu speichen, was natürlich nicht sinnvoll ist. Wir sollten wirklich für jeden neuen Anruf einen neuen Namen wählen. Dies ist nicht so einfach, wie es sich anhört - sie müssen sicherstellen, dass der verwendete Algorithmus auch noch mit mehreren Anrufen, die zur selben Zeit ankommen, funktioniert. Glücklicherweise hatte der hilfsbereite Programmierer von CapiSuite das selbe Problem, sodass wir seinen (hmmm... meinen?) Code verwenden könenn.
Das Python-Modul cs_helpers.py enthält einige hilfreiche Funktionen, die von den Standard-Skripten, die mit CapiSuite geliefert werden, benötigt werden, die aber auch in Ihren eigenen Skripten ganz nützlich sein können. Es enthält die Funktion uniqueName, die genau das macht, was wir hier brauchen. Die Syntax lautet:
filename=cs_helpers.uniqueName(directory,prefix,sufix)
Die Funktion sucht einen neuen eindeutigen Dateinamen im angegebenen directory. Der erzeugte Dateiname ist "prefix-XXX.suffix", wobei XXX die nächste freie Nummer, angefangen bei 0, ist. Die nächste freie Nummer wird in der Datei prefix-nextnr vermerkt und der erzeugte Name wird zurück gegeben.
Wir können diesen Aufruf einfach in unser Skript einbauen:
Beispiel 2.3. Verwendung eindeutiger Dateinamen
import capisuite,cs_helpers my_path="/path/to/the/just/created/capisuite-examples/" def callIncoming(call,service,call_from,call_to): try: if (call_to=="123"): filename=cs_helpers.uniqueName(my_path,"voice","la") capisuite.connect_voice(call,10) capisuite.audio_send(call,my_path+"announce.la") capisuite.audio_send(call,my_path+"beep.la") capisuite.audio_receive(call,filename,20,3) capisuite.disconnect(call) else: capisuite.reject(call,1) except capisuite.CallGoneError: capisuite.disconnect(call)
Wenn es Sie interessiert, welche anderen Funktionen in cs_helpers.py definiert sind, schauen Sie sich die Referenz unter dem „cs_helpers.py“ an.
Als letzten Schritt möchte ich Ihnen zeigen, wie Fax-Erkennung und -Empfang funktionieren und wie man vom Sprach- in den Fax-Modus umschaltet.
Hier ist das letzte und komplizierteste Beispiel dieses Abschnitts. Es führt vier neue CapiSuite-Funktionen ein und zeigt, wie die Funktionalität in eine andere Funktion aufgeteilt werden werden kann, die von callIncoming genutzt wird. Es gibt viele änderungen, die weiter unten beschrieben sind - aber die meisten davon sollten nahezu selbsterklärend sein. Ich glaube daher nicht, dass dieser letzte Schritt zu umfangreich ist. Und Sie wollen ja nicht noch 10 weitere Schritte lesen, stimmt's? ;-)
Beispiel 2.4. Hinzufügen der Fax-Funktionen
import capisuite,cs_helpers,osmy_path="/path/to/the/just/created/capisuite-examples/" def callIncoming(call,service,call_from,call_to): try: if (call_to=="123"): filename=cs_helpers.uniqueName(my_path,"voice","la") capisuite.connect_voice(call,10) capisuite.enable_DTMF(call)
capisuite.audio_send(call,my_path+"announce.la",1)
capisuite.audio_send(call,my_path+"beep.la",1) capisuite.audio_receive(call,filename,20,3,1) dtmf=capisuite.read_DTMF(call,0)
if (dtmf=="X"):
if (os.access(filename,os.R_OK)):
os.unlink(filename) faxIncoming(call)
capisuite.disconnect(call) else: capisuite.reject(call,1) except capisuite.CallGoneError: capisuite.disconnect(call) def faxIncoming(call): capisuite.switch_to_faxG3(call,"+49 123 45678","Test headline")
filename=cs_helpers.uniqueName(my_path,"fax","sff") capisuite.fax_receive(call,filename)
Glückwunsch. Sie haben mein kleines Tutorial beendet. Jetzt sind Sie dran - Sie können ein bisschen mit dem erstellten Skript herumspielen und versuchen, es noch weiter zu vervollständigen. Es gibt noch viel zu tun - empfangene Anrufe per E-Mail an den Benutzer schicken, Verbindungen protokollieren, ... Wenn Sie dieses Skript vervollständigen wollen, ist der „CapiSuite-Befehlsreferenz“ hilfreich. Sie können auch hier weiter lesen, um einen kurzen Blick auf das Idle-Skript zu werfen, gefolgt von einem schnellen überblick über die Struktur der Standard-Skripte, die mit CapiSuite geliefert werden.