3.11.2022
Ab Asterisk 11 lassen sich Textnachrichten über das SIP-Protokoll verschicken. Vorrausetzung ist, dass die Endgeräte diese Funktion ebenfalls unterstützen. Die meisten Softphones sind dazu in der Lage. Für den Empfang der Texte müssen die empfangenen Endgeräte zudem eingeschaltet sein. Eine Zwischenspeicherung findet leider nicht statt.
Die Textübertragung mit SIP geht laut den Anregungen von Conrad de Wet unter https://github.com/InnovateAsterisk/Browser-Phone und nach einer Anleitung von Gerd (einen ganz großen Dank an dieser Stelle) ganz einfach. Getestet auf Raspberry Pi 3 B+, Raspbian vom Februar 2020, und Asterisk 16.2.1. Die Textübermittlungen wurden mit den Softphones PhonerLite, Sipnetic, Linphone für Android und MicroSip getestet.
Damit man Textnachrichten über dafür geeignete Softphones verschicken und empfangen kann, müssen die sip.conf und extensions.conf um ein paar Einträge ergänzt werden. Das ist alles.
Egänzungen in der sip.conf:
[general] ; Wir sind in der sip.conf ; Am Ende von [general] sind folgende drei Zeilen ; für die Textübermittlung einzutragen. accept_outofcall_message=yes ; muss unbedingt auf yes stehen auth_message_requests=no outofcall_message_context=textmessages
Ergänzungen in der extensions.conf:
; Wir sind in der extensions.conf [textmessages] ; Nachfolgend werden alle Telefonanschlüsse aufgeführt, ; die schreiben und lesen dürfen. Diese extensions (Nummern) sind ; bereits in den entsprechenden Contexten und in der sip.conf ; definiert. exten => 1001,1,Gosub(send-text,s,1,(1001)) exten => 1002,1,Gosub(send-text,s,1,(1002)) exten => 1003,1,Gosub(send-text,s,1,(1003)) ; die Nummern 1001, 1002 und 1003 dürfen also ; in diesem Beispiel ; Texte verschicken und empfangen. Man kann das ; natürlich eleganter schreiben. Kommt später. ; Und das muss auch noch reinkopiert werden: [send-text] exten => s,1,NoOp(Sending Text To: ${ARG1}) exten => s,n,Set(PEER=${CUT(CUT(CUT(MESSAGE(from),@,1),<,2),:,2)}) exten => s,n,Set(FROM=${SHELL(asterisk -rx 'sip show endpoint ${PEER}' | grep 'callerid ' | cut -d':' -f2- | sed 's/^\ *//' | tr -d '\n')}) exten => s,n,Set(CALLERID_NUM=${CUT(CUT(FROM,>,1),<,2)}) exten => s,n,Set(FROM_SIP=${STRREPLACE(MESSAGE(from),<sip:${PEER}@,<sip:${CALLERID_NUM}@)}) exten => s,n,MessageSend(sip:${ARG1},${FROM_SIP}) exten => s,n,Hangup()
Mir was es zu anstrengend für die Nummern 1000 bis 1999 Nummer für Nummer 1000 Zeilen zu schreiben, weshalb ich [textmessages] umgeschrieben habe:
[textmessages] exten => _1XXX,1,Gosub(send-text,s,1(${EXTEN})) ; mit einer Zeile sind die Nummern 1000 bis 1999 abgedeckt.
Nach den Änderungen an der sip.conf und an der extensions.conf habe ich in der Asterisk-Konsole den Befehl „core reload“ ausgeführt. Danach wurden Änderungen an der extensions.conf mit „dialplan reload“ akzeptiert.
Vom Softphone Sipnetic ging das Verschicken von Textnachrichten an PhonerLite manchmal nur, wenn ich die Zielnummer neu eingegeben hatte. Ich konnte nicht direkt antworten. Es gelang mir eine Nachricht an mein IP-Telefon Thomson TB-30 zu verschicken. Der empfangene Text blinkte dann auf dem Display. Er verschwand erst nach dem Unterbrechen der Stromversorgung.
Leider speichert Asterisk die Texte nicht zwischen. Texte kommen nur an, wenn das Softphone der Zielnummer eingeschaltet ist. Ein Telefongespräch muss nicht laufen. Ob die Textnachricht tatsächlich angekommen ist, erfährt man nicht. Man erfährt nur, ob die Textnachricht erfolgreich abgeschickt worden ist.
Nachtrag vom 21.9.2021: Leider hatte mit dem obigen Skript das Chatten auf dem Android-Smartphone Sipnetic nicht funktioniert. Wollte man auf einen Text direkt antworten, kam eine Fehlermeldung, weil die SIP-URI (die Sip-Adresse) der eingehenden Textnachricht falsch übermittelt wurde.
Das Skript in der extensions.conf habe ich deshalb angepasst und es läuft bei mir einwandfrei auf Asterisk 16.2.1:
; Auszug aus der extensions.conf ; Skript für das Versenden von Texten über das SIP-Protokoll ; getestet auf Asterisk 16.2.1 [textmessages] exten => _1XXX,1,Gosub(send-text,s,1,(${EXTEN})) ; [send-text] exten => s,1,NoOp(Sending Text To: ${ARG1}) exten => s,n,NoOp(Message from: ${MESSAGE(from)}) exten => s,n,NoOp(Message to: ${MESSAGE(to)}) exten => s,n,NoOp(Message body: ${MESSAGE(body)}) exten => s,n,Set(PEER=${CUT(CUT(CUT(MESSAGE(from),@,1),<,2),:,2)}) exten => s,n,NoOp(peer: ${PEER}) exten => s,n,MessageSend(sip:${ARG1},${PEER}) exten => s,n,Hangup() ; ohne die NoOp-Anweisung mitgezählt besteht [send-text] aus drei Zeilen.
Ich habe noch nicht ganz verstanden, warum es funktioniert. In der sip.conf habe ich die einzelnen Telefonnummern der Nebenstellen recht schlicht gehalten und immer CallerIDs versehen. Hier ein Muster-Beispiel:
; Wir sind in der sip.conf ; Jede Ähnlichkeit mit der Wirklichkeit ist rein zufällig. ; Musteraufbau eines Accounts mit der Nummer 1444 [1444] ; Magdalena Andersson type=friend context=statsminister secret=skatteparadisetsverige host=dynamic username=1444 canreinvite=no port=5064 dtmfmode=rfc2833 callerid = "Magdalena Andersson" <1444>
In Sipnetic funktioniert jetzt das Chatten einwandfrei:
Im Asterisk-CLI mit Verbose 3 ist folgendes zu sehen:
Aus Sicherheitsgründen sind die IP-Adressen rot übermalt. Zu sehen ist eine Text-Konversation zwischen den Nummern 1003 und 1009. Die 1003 ist ein Sipnetic-Sofphone auf Android und die 1009 ist PhonerLite unter Windows.
Verbesserte Version mit Fehlermeldung bei Empfangsstörungen: Störend ist, dass keine Fehlermeldung erfolgt, wenn der Empfänger der Textnachricht offline ist, weil er zum Beispiel seinen PC ausgeschaltet hat oder das Softphone abgeschaltet ist. Das nachfolgende verbesserte Script schickt eine Fehlermeldung zurück, falls die Nachricht nicht angekommen ist.
[textmessages] exten => _1XXX,1,Gosub(send-text,s,1,(${EXTEN})) ; in GOSUB ist die erste Variable EXTEN und entspricht ; in [send-text] ARG1 ; EXTEN enthält Empfänger-Nummer, z.B 1003 ; Zum Versenden brauchen wir die Ziel-Telefonummer, im Beispiel die 1003. Die haben wir schon. ; Dann brauchen wir noch die Absender-Nummer, z.B. die 1009. Diese Nummer zu erhalten ist das eigentliche Problem. ; Nach dem Versenden der Nachricht, stellen wir fest, ob sie erfolgreich war. Wenn nicht lassen wir ; eine Fehlermeldung in umgekehrter Richtung verschicken. [send-text] ; Das sollte man wissen: ; NoOP hat keine Funktion, dient nur zur Info für Fehlersuche exten => s,1,NoOp(Sending Text To: ${ARG1}) ; von [send-text] ARG1 enthält Empfänger-Telefon-Nummer, z.B 1003 exten => s,n,NoOp(Message from: ${MESSAGE(from)}) ; vollständige SIP-Adresse des Absenders. Da steht zu viel drin. exten => s,n,NoOp(Message to: ${MESSAGE(to)}) ; vollständige SIP-Adresse des Empfängers, hier nur zur Info exten => s,n,NoOp(Message body: ${MESSAGE(body)}) ; Inhalt der Textnachricht ; Nachfolgend geht es jetzt richtig los mit dem Skript exten => s,n,Set(PEER=${CUT(CUT(CUT(MESSAGE(from),@,1),<,2),:,2)}) ; schneidet die Absender-Telefon-Nummer heraus. exten => s,n,NoOp(peer: ${PEER}) ; in PEER steht jetzt nur die Absender-Telefonnummer, z.B. 1009 exten => s,n,MessageSend(sip:${ARG1},${PEER}) ; versendet Nachricht nach 1003 (ARG1) mit Absenderadresse 1009 (PEER) ; Nachricht wurde abgeschickt. Nachfolgend die Fehlerbehandlung exten => s,n,NoOp(Message send status: ${MESSAGE_SEND_STATUS}) ; zeigt den Status des Versendes an exten => s,n,GotoIf($["${MESSAGE_SEND_STATUS}" = "SUCCESS"]?erfolg:failed) ; erfolgreich versendet, gehe zu Zeile erfolg, ; andernfalls zur Zeile failed exten => s,n(erfolg),Hangup() ; bei erfolgreicher Versendung die Verbindung trennen exten => s,n(failed),Set(MESSAGE(body)=Übertragungsfehler zum Teilnehmer ${ARG1}: ${MESSAGE_SEND_STATUS}) ; obige Zeile: Verfasst den Nachrichtinhalt im Falle eines Fehlers exten => s,n,MessageSend(sip:${PEER},${ARG1}) ; schickt den neuen Nachrichteninhalt mit der Fehlermeldung ; von 1009 nach 1003. ARG1 und PEER wurden vertauscht exten => s,n,Hangup() ; Verbindung trennen. Das wars schon. ; Falls die Nachricht nicht ankommt, erscheint beim Absender eine Fehlermeldung. ; Richtet sich die Textnachricht an ein normales Telefon, das erreichbar ist, ; erscheint keine Fehlermeldung, obwohl es keine Texte empfangen kann.
Abgefragt wird der Status von MESSAGE_SEND_STATUS. Liefert diese Funktion nicht SUCCESS zurück, wird eine Fehlermeldung an den Absender geschickt.
Wenn man jedoch versucht an ein ganz normales Telefon, das keine Texte empfangen kann, eine Nachricht zu schicken, erfolgt leider kein Fehlermeldung, falls dieses Telefon erreichbar – d.h. angeschlossen – ist.
Asterisk-Telefonserver auf einem Raspberry Pi – Installation, Konfiguration, Programmierung, SIP, IAX2, AGI-Skripte, Sicherheit und Tipps zum praktischen Betrieb – 2.11.2022: Diese Seite richtet sich an jene, welche einen Asterisk-Telefon-Server auf einem Raspberry Pi betreiben möchten und später ein kleines Netzwerk aus Asterisk-Servern planen, um ein eigenständiges Telefonnetz aufzubauen. Los geht es mit der Installation von Raspbian und Asterisk auf einem Raspberry Pi und dann nach Lust und Laune immer tiefer in die Programmierung von Asterisk. Die Themen werden laufend erweitert.
Selbstverständlich muss es nicht unbedingt ein Raspberry Pi sein. Andere Linux-Rechner gehen auch. – weiter – |