|
|
Versenden von SMS mittels Mobiltelefon[Bearbeiten] EinleitungIm Forum kommt immer häufiger die Frage "Wie werden Textnachrichten mittels eines handelsüblichen Mobilfunkgerätes versandt?". Im Rahmen einer Projektarbeit entstand dabei eine recht umfangreiche Bibliothek zu diesem Thema. Diese soll hier nun kurz vorgestellt werden. Die Software beinhaltet unter anderem:
Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. einen Text in das PDU Format zu transformieren. Ich habe mich aber lieber auf mehr und damit für andere auch verständlicheren Code beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines Erachtens zum Verständnis bei. [Bearbeiten] HardwareIch arbeite selber mit einem Siemens SL55 Mobiltelefon. In einschlägigen Auktionshäusern sind diese betagten Mobilfunktelefone sehr günstig zu erwerben und damit ideal zum experimentieren geeignet. Neben dem Mobilfunktelefon wird natürlich auch ein entsprechendes serielles Datenkabel benötigt. Das Datenkabel wird über Pegelwander direkt mit dem Mobiltelefon und dem Mikrocontroller verbunden. Dadurch ist es möglich die serielle Schnittstelle des Mobilfunkgerätes anzusprechen. Als erstes sollte die Kommunikation mit einem Computer überprüft werden. Dazu ist das Datenkabel an das Mobilfunkgerät anzuschließen. Mit einem Terminalprogramm wie hterm kann nun eine Kommunikation erfolgen. Dazu muss die serielle Schnittstelle entsprechen eingestellt werden. Bei dem SL55 ist eine Baudrate von 19200 im 8N1 Modus erforderlich. Bei der Kommunikation mit einem Mikrocontroller ist darauf zu achten, dass die meisten Datenkabel einen Pegelwandler enthalten. Das bedeutet, dass der Pegel des Mobilfunkgerätes (meist High-Pegel 3,3V) auf den Pegel der seriellen Schnittstelle angepasst wird (High-Pegel -15V). Ein Mikrocontroller arbeitet dagegen mit Spannungen von 5V bzw. 3,3V. Die Anpassung geschieht mittels eines Pegelwandlers wie dem MAX232. Dabei ist zu beachten, dass im Kommunikationsweg nun 2 Pegelwandler vorhanden sind (Datenkabel und am Mikrocontroller). Das bedeutet, dass für eine Kommunikation mit einem Mobilfunkgerät die Leitungen Rx und Tx gekreuzt werden müssen. Dieser Umstand hat mir am Anfang relativ viel Zeit gekostet, da eine einfache Kommunikation mit einem Computer 1:1 geschehen kann. Es muss also zwischen Datenkabel und Mikrocontroller noch ein gekreuztes serielles Kabel dazwischen geschaltet werden. Eine weitere Möglichkeit ist natürlich der direkte Anschluss der seriellen Schnittstelle des Mikrocontrollers am Mobiltelefon. Dabei ist zu beachten, dass im Fall einer Spannungsversorgung des Mikrocontrollers von 5V Pegelwandler für die Leitungen Tx und Rx nötig sind. Das können im einfachsten Fall 3,3V Z-Dioden sein. Ich habe mich dafür entschieden, gleich eine kleine Platine mit einem ATmega8 anzufertigen. Dabei hab ich darauf geachtet, dass ich über Jumper die Leitungen Tx und Rx 1:1 bzw. gekreuzt schalten kann. Dadurch kann ich ohne zusätzliches gekreuztes serielles Kabel eine Kommunikation mit dem Mobilfunkgerät aufbauen. Die aktuelle Software passt nicht mehr in einen ATmega8. Ich arbeite aktuell mit einem ATmega32. Mit ein paar Anpassungen sollte es aber problemlos möglich sein, den Code in der Größe stark zu reduzieren. So können z.B. die Bibliotheken zur Ansteuerung des Temperatursensors entfallen (twi.c, twi.h, ds75lv.c und ds75lv.h). Alternativ dazu wäre auch die Verwendung der pinkompatiblen Controller ATmega168 bzw. ATmega328 denkbar. Diese haben 16KiB bzw. 32KiB Flash und sind unwesentlich teurer als der ATmega8 (siehe MyAVR). [Bearbeiten] SoftwareAllgemein wird bei dem Softwarekonzept eine Mischung aus Interrupt und Polling genutzt. So werden z.B. Nachrichten vom Mobilfunkgerät über die serielle Schnittstelle des Mikrocontroller mittels UART Receive Interrupt empfangen, das Senden von Befehlen erfolgt aber mittels Polling. Wie die Kommunikation mit der seriellen Schnittstelle des Mikrocontrollers funktioniert, ist in einem anderen Artikel nachzulesen (siehe Der UART) und soll an dieser Stelle vorausgesetzt werden. Für die einfachere Arbeit mit der seriellen Schnittstelle habe ich die Low-Level Funktionen auf die Standard Ein- und Ausgabe umgeleitet. Dadurch können die allseits bekannten Funktionen wie printf oder scanf für eine komfortable Kommunikation genutzt werden. Das vergrößert zwar den Code, ist aber dank einfacherer formatierten Ein- und Ausgabe mehr als gerechtfertigt. c AT-Kommandos sind spezielle Steuerkommandos, welche es ermöglichen das Mobilfunkgerät zu steuern. Für jedes Mobilfunkgerät gibt es einen AT-Command Set in dem alle relevaten Kommandos erklärt sind. Diese Kommandos sollten vorab mit einem Terminalprogramm wie hterm am Computer getestet werden. Von Mobilfunkgerät zu Mobilfunkgerät kann es bei den einzelnen Kommandos kleinere Unterschiede geben, so dass evtl. auch der Quellcode angepasst werden müsste. [Bearbeiten] Das PDU FormatViele Mobilfunkgeräte können nur im PDU Format Textnachrichten versenden. Bei neueren Mobilfunkgeräten ist es zum Teil möglich, auch im Klartext Nachrichten zu verschicken. Das PDU Format soll an dieser Stelle einmal am Beispiel des AT-Kommandos AT+CMGS zum versenden von Textnachrichten näher erläutert werden. Eine Kurznachricht mit dem Inhalt „Hallo Welt“ an die Nummer 01621234567 sieht z. B. folgendermaßen aus: AT+CMGS=22<cr> Die Zeichen <cr> und <subst> sind dabei Steuerzeichen, welche das Mobiltelefon benötigt. Das Steuerzeichen <cr> stellt dabei ein new line (dezimal 10) mit anschließendem carriage return (dezimal 13) dar und <subst> ein so genanntes substitute (dezimal 26). Im Folgenden soll nun einzeln erläutert werden, inwieweit die Nachricht „Hallo Welt“ in das PDU Format kodiert werden kann. Nach dem AT Kommando folgt die Länge der Hex Paare der PDU Zeichenkette ohne die beiden führenden Nullen. Das heißt, dass im obigen Beispiel 23 Hex Paare an das Mobiltelefon gesendet werden, aber lediglich 22 angegeben werden müssen. Die eigentliche PDU Zeichenkette beginnt mit „00“ und gibt die Länge der Short Massage Service Centre Nummer (SMSC) wieder. Die Längenangabe von null bedeutet, dass das Mobiltelefon selbst die eingespeicherte SMSC Nummer wählt. Mit Hilfe des zweiten Hex Paares können verschiedene Optionen eingestellt werden. Die Angabe von „01“ bedeutet, dass die SMS an das SMSC geschickt wird. Das nächste Hex Paar dient zum Zuordnen weiterer Nachrichten wie z. B. Berichten und ist die Referenznummer der Nachricht. Die Angabe von „00“ veranlasst dabei das Mobiltelefon dazu, die Referenznummer selbst zu wählen. Als nächstes folgen die Angabe der Länge der Empfängernummer, der Nummerntyp und entsprechend nachfolgend die Nummer. Die Länge der Empfängernummer wird durch das Hex Paar „0B“ angegeben und ist somit 11 Zeichen lang. Das Hex Paar „81“ gibt an, dass die nachfolgende Empfängernummer eine nationale Nummer ist. Bei der Angabe der Empfängernummer ist zu beachten, dass die einzelnen Ziffern der Paare der Nummer vertauscht werden. Aus der Nummer 01 62 12 34 56 7 wird dementsprechend 10 26 21 43 65 F7. Wie im Beispiel zu sehen, werden unvollständige Paare mit „F“ aufgefüllt. Die nächsten beiden Hex Paare sind der so genannte Protocoll Identifier und das Data Coding Scheme. Hier genügt jeweils die Angabe von „00“. Es folgt die Angabe der Länge der zu sendende Nachricht, hier „0A“. Im Anschluss daran wird die eigentliche Nachricht als PDU codierter String angehängt. Die Vorgehensweise ist dabei in unten stehender Tabelle dargestellt.
Bei der Umwandlung wird zunächst der ASCII Text in eine 7Bit Darstellung überführt, indem das erste Bit gelöscht wird. Das bedeutet, dass nicht der gesamte ASCII Zeichensatz zur Verfügung steht (Zeichensatz siehe 3GPP 23.038). Als nächstes wird die 7Bit Darstellung wiederum in eine 8Bit Darstellung umgewandelt, indem beim ersten Zeichen das letzte Bit des nachfolgenden Zeichens am Anfang angefügt wird (siehe rote Markierungen in obiger Tabelle). Beim zweiten Zeichen werden entsprechend die letzten beiden Bits des nachfolgenden Zeichens angefügt. Dies wird solange fortgeführt, bis die kompletten 7Bit eines Zeichens an das vorhergehende angefügt worden und der Algorithmus von Anfang an beginnt. Stehen keine Zeichen mehr zur Verfügung, so wird mit Nullen aufgefüllt, bis das Oktett vollständig ist (siehe blaue Markierungen obiger Tabelle). Durch die Umwandlung von 8Bit ASCII Zeichen in eine PDU Zeichenkette konnte im obigen Beispiel ein Zeichen bei der Übertragung eingespart werden. Die zu übertragende Nachricht „Hallo Welt“ wird damit durch „C8309BFD065DCB6C3A“ repräsentiert. [Bearbeiten] FunktionsbeschreibungIch beschränke mich bei der Funktionsbeschreibung lediglich auf die wesentlichen Funktionen in sms.c. Die Funktionen der anderen Bibliotheken wie die der seriellen Schnittstelle, des Temperatursensors und der I2C-Schnittstellen sind der Quelltextdokumentation zu entnehmen. Die Dokumentation der einzelnen Funktionen erfolgt mittels Doxygen tags. Das heißt, mit Hilfe von Doxygen kann eine komplette HTML-Hilfe generiert werden. [Bearbeiten] sms_init(void)Diese Funktion initialisiert die serielle Schnittstelle des Mikrocontrollers, leitet die Low-Level Funktionen der serielle Schnittstelle auf die Standard Ein- und Ausgabe um und nimmt einige Konfigurationen am Mobiltelefon vor. So wird z.B. das Echo beim senden von AT-Kommandos deaktiviert und der Speicherplatz für empfangene Textnachrichten auf den internen Speicher des Mobiltelefons eingestellt. Zudem wird die new message indication eingestellt. Das bedeutet, dass bei einer eingehenden Textnachricht dies über die serielle Schnittstelle dem Mikrocontroller mitgeteilt wird. Das erspart lästiges pollen nach neu eingetroffenen Textnachrichten. Des Weiteren werden ebenso die ersten Telefonnummern aus der SIM-Karte ausgelesen und zum späteren Vergleich in einer Datenstruktur abgelegt. [Bearbeiten] sms_time( unsigned char *year,unsigned char *month, unsigned char *day,unsigned char *hour, unsigned char *minute,unsigned char *second)Diese Funktion ließt das Datum und die aktuelle Zeit des Mobiltelefons aus. Beispielaufruf:
[Bearbeiten] sms_send(char* zielnr, char* nachricht)Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer Beispielaufruf:
Dabei ist zu beachten, dass SMS_TELNR in der Headerdatei sms.h korrekt angegeben werden muss. Diese Nummer wird ebenso zur Reaktion auf eingehende Anrufe genutzt (siehe sms_state_machine). Der Aufruf kann auch direkt erfolgen:
[Bearbeiten] sms_decode (char* pdu, SMS_DECODE_DATA_T* data)Diese Funktion dekodiert empfangene Textnachrichten und legt diese in einer Datenstruktur ab. Die Datenstruktur ist dabei folgendermaßen aufgebaut:
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.
[Bearbeiten] sms_display_text(char* nachricht)Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar. Beispielaufruf:
[Bearbeiten] SMS_MSG sms_state_machine(void)Diese Funktion wertet alle einkommenden Daten des Mobiltelefons aus und wird in der main loop fortlaufend ausgeführt. Der Rückgabewert der Funktion entspricht dem zuletzt empfangenen Datensatz.
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c. Beispielhaft könnte diese wie folgt aussehen:
Die Schlüsselwörter müssen dabei immer aus Kleinbuchstaben bestehen, da die eintreffende Textnachricht in Kleinbuchstaben konvertiert wird. Das erleichtert den Vergleich und verhindert ungewollte Schreibfehler bei Groß- und Kleinschreibung. Die Definition der Trennzeichen zwischen den einzelnen Schlüsselwörtern erfolgt in der Headerdatei sms.h. Hier beispielhaft Komma, Semikolon, Doppelpunkt und Leerzeichen:
Eine eingehende Textnachricht mit dem Inhalt "set, test" würde demnach die Funktionen sms_cmdset und sms_cmdtest ausführen. Dabei ist zu beachten, dass die angelegten Funktionen stets vom Typ
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:
Die eigentliche Funktion kann in die Datei main.c geschrieben werden. [Bearbeiten] Verwendung der Bibliothek in eigenen ProjektenDie Software wird als komplett kompilierbares Projekt zum Download bereitgestellt in dem auch die Hauptfunktionen und deren Anwendung erläutert werden. Zunächst müssen natürlich einige Einstellungen vorgenommen werden. [Bearbeiten] VoreinstellungenDie Baudrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über
geändert werden. Die Einstellung von 19200 Baud sollte aber bei den meisten Mobiltelefonen korrekt sein. Des Weiteren kann in der Headerdatei auch die Größe des Empfangspuffer über
eingestellt werden. Der relativ groß eingestellte Puffer kommt durch das PDU Format eingehender Textnachrichten zustande. Neben der eigentlichen codierten Nachricht wird noch der Header mit Telefonnummer, Zeitstempel und anderen Angaben zum Mikrocontroller übertragen. Die Textnachricht kann maximal 160 Zeichen enthalten. Im PDU Format werden 240 Zeichen für diese Textnachricht übertragen. Die minimale Puffergröße sollte
angepasst werden. Dieses Makro kann zum einen genutzt werden, um mit Hilfe von sms_send() Textnachrichten zu verschicken, zum anderen dient es aber auch der Anrufererkennung in sms_state_machine(). Ein weiteres wichtiges Makro ist
Darüber lässt sich steuern, wie viele Telefonnummern aus der SIM-Karte zum Vergleich mit herangezogen werden sollen. Das heißt, ein Wert von fünf würde bedeuten, dass die ersten fünf Telefonnummern der SIM-Karte analog zu SMS_TELNR in der sms_state_machine ausgewertet werden. Ein korrekter Vergleich mit den Telefonnummern kann über die Rückgabewerte der Funktion sms_state_machine realisiert werden. Neben der Telefonnummer können in der Headerdatei auch die Trennzeichen für die Schlüsselwörter einer empfangenen Textnachricht eingestellt werden.
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen. [Bearbeiten] Nutzung der FunktionenNeben der bereits erfolgten kurzen Funktionsbeschreibung, soll an dieser Stelle noch einmal auf die Besonderheit der Funktion sms_state_machine() eingegangen werden. Die Funktion wird zyklische in der main loop aufgerufen und hat als Rückgabewert folgenden Aufzählungstyp SMS_MSG:
Über diesen Aufzählungstyp kann der zuletzt empfangene Datensatz vom Mobiltelefon verifiziert werden. So bedeutet der Rückgabewert SMS_RETRIEVE_TELNR z. B. dass ein eingehender Anruf mit der in SMS_TELNR angegebenen Telefonnummer bzw. mit den aus der SIM-Karte ausgelesenen TElefonnummern (siehe SMS_TELNR_LIST_MAX) erfolgte. Auf diesen Anruf kann nun in der main loop entsprechend reagiert werden. Das erfolgt nach dem Schema:
Die Telefonnummer des letzten Anrufers kann mit Hilfe der globalen Variable sms_last_caller weiter verarbeitet werden. So wäre es z. B. denkbar, eine Textnachricht an diesen zu senden. Neben SMS_RETRIEVE_TELNR ist ebenso der Rückgabewert SMS_MSG_DECODE von Relevanz. Er zeigt an, dass eine Textnachricht empfangen, decodiert und in der Datenstruktur sms_dec_data abgelegt wurde. Die Struktur der globalen Variable sieht dabei wie folgt aus:
So kann über sms_dec_data.nachricht die zuletzt eingegangene Textnachricht oder über sms_dec_data.date.day der Tag ausgelesen werden. Ein weiterer wichtiger Aspekt der Bibliothek ist das Textphrasing empfangener Textnachrichten und das ausführen entsprechender Funktionen bei bestimmten Schlüsselwörtern. Nähere Erläuterungen zur Vorgehensweise und Einstellung der Schlüsselwörter sind dazu bereits in der obigen Funktionsbeschreibung zu sms_state_machine erfolgt. [Bearbeiten] DownloadSoftware Stand 28.12.2010 (Bugfix in sms_decode behoben)Software Stand 08.05.2010 Doxygen Hilfe des Projektes
AT Command Set For L55 Siemens Mobile Phones And Modems [Bearbeiten] Quellen[Bearbeiten] Allgmeine Quellen zum Thema
[Bearbeiten] Forenbeiträge |