Versenden von SMS mittels Mobiltelefon
Einleitung
Im 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:
- Reaktion auf einen bestimmten Anrufer
- Versand von Textnachrichten im PDU Format
- Auslesen von Textnachrichten im PDU Format und Decodierung
- Auslesen des aktuellen Datums und der Zeit des Mobiltelefons
- Anzeigen von Text auf dem Display des Mobiltelefons
- Textphrasing von empfangenen Textnachrichten und Ausführen vorher eingestellter Aktionen/Funktionen auf bestimmte Schlüsselwörter
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.
Hardware
Ich 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).
Software
Allgemein 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.
Das PDU Format
Viele 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>
0001000B811026214365F700000AC8309BFD065DCB6C3A<subst>
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.
ASCII Zeichen | H | a | l | l | o | W | e | l | t | |
8 Bit Binär | 01001000 | 01100001 | 01101100 | 01101100 | 01101111 | 00100000 | 01010111 | 01100101 | 01101100 | 01110100 |
7 Bit Binär | 1001000 | 1100001 | 1101100 | 1101100 | 1101111 | 0100000 | 1010111 | 1100101 | 1101100 | 1110100 |
8 Binär PDU | 11001000 | 00110000 | 10011011 | 11111101 | 00000110 | 01011101 | 11001011 | 01101100 | 00111010 | |
8 Bit Hex PDU | C8 | 30 | 9B | FD | 06 | 5D | CB | 6C | 3A |
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.
Funktionsbeschreibung
Ich 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.
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.
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:
...
unsigned char year=0;
unsigned char month=0;
unsigned char day=0;
unsigned char hour=0;
unsigned char minute=0;
unsigned char second=0;
sms_time (&year, &month, &day, &hour, &minute, &second);
...
sms_send(char* zielnr, char* nachricht)
Diese Funktion sendet ein Textnachricht an eine bestimmte Zielnummer Beispielaufruf:
...
sms_send(SMS_TELNR,"Hallo Welt");
...
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:
...
sms_send("01621234567","Hallo Welt");
...
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:
/**
* @brief
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht
*/
typedef struct {
uint8_t year; /**< Jahresangabe YY */
uint8_t month; /**< Monatsangabe MM */
uint8_t day; /**< Tagangabe DD */
uint8_t hour; /**< Stundenangabe hh */
uint8_t minute; /**< Minutenangabe mm */
uint8_t second; /**< Sekundenangabe ss */
} DATE_T;
/**
* @brief
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht
*/
typedef struct {
char nachricht[SMS_MESSAGE_MAX_LEN+1]; /**< decodierte PDU Nachricht */
char telnr[SMS_TELNR_MAX_LEN+1]; /**< Telefonnummer des Absenders */
DATE_T date; /**< Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */
} SMS_DECODE_DATA_T;
Der Funktion muss dabei der komplette PDU String des AT-Kommandos AT+CMGR übergeben werden.
#define uart_maxstrlen 160
...
SMS_DECODE_DATA_T sms_dec_data;
char sms_tmp[UART_MAXSTRLEN+1]={'0'};
int sms_index=0;
int dummy=0;
...
printf("AT+CMGR=%i\r\n",sms_index);
gets(sms_tmp); // führendes \r\n verwerfen
scanf("+CMGR: %i,,%i\r\n%s\r\n",&dummy,&dummy,sms_tmp);
...
sms_decode(sms_tmp,&sms_dec_data);
...
sms_display_text(char* nachricht)
Diese Funktion stellt eine Nachricht auf dem Mobiltelefon-Display dar. Beispielaufruf:
...
sms_display_text("Hallo Welt");
...
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.
typedef enum {
SMS_OK, /**< OK von Mobiltelefon empfangen */
SMS_ERROR, /**< ERROR von Mobiltelefon empgangen */
SMS_MSG_DECODE, /**< Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */
SMS_INCOMING_RING, /**< eingehender Anruf */
SMS_CANCEL_RING, /**< eingehender Anruf wurde abgewiesen */
SMS_REQUEST_TELNR, /**< Telefonnummer des eingehenden Anruft wurde abgefragt */
SMS_RETRIEVE_TELNR, /**< Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T
verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */
SMS_RETRIEVE_nTELNR, /**< Anrufer wurde abgewiesen, Telefonnummer ermittelt und <b>nicht</b> korrekt mit \ref SMS_TELNR bzw. \ref
SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */
SMS_IDLE /**< empfangene Zeichenkette wurde nicht in sms_state_machine "gefunden" (kein Eintrag) */
} SMS_MSG;
Diese Funktion führt ebenso das Textphrasing bei empfangenen Textnachrichten durch. Die Zuordnung von Schlüsselwörtern erfolgt wiederum durch eine spezielle Datenstruktur:
typedef struct SMS_CMD_LIST_S{
char cmd[10]; /**< Zeichenkette für Kommando */
uint8_t (*fp)(uint8_t dat); /**< Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */
}SMS_CMD_LIST_T;
Die Parametrisierung der Datenstruktur erfolgt in der Datei sms.c. Beispielhaft könnte diese wie folgt aussehen:
const SMS_CMD_LIST_T sms_cmd_list[] = {
{"set",sms_cmdset},
{"test",sms_cmdtest}
};
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:
#define SMS_DELIMITER ",;: "
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
uint8_t foo (uint8_t dat);
sind. In der Bibliothek muss der entsprechende Prototyp in der Datei sms.h angegeben werden. Z. B könnte das folgendermaßen aussehen:
extern uint8_t foo (uint8_t dat);
Die eigentliche Funktion kann in die Datei main.c geschrieben werden.
Verwendung der Bibliothek in eigenen Projekten
Die 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.
Voreinstellungen
Die Baudrate für die Kommunikation mit dem Mobiltelefon kann in der Datei uart.h über
/**
* definiert Baudrate für serielle Schnittstelle
*/
#define UART_BAUD 19200UL
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
/**
* Definiert die maximale Anzahl von Zeichen, welche über die
Rx-Interruptroutine empfangen werden können.
* <br> Dient damit auch zum Festlegen der Größe der globalen Variable /ref
uart_string.
*/
#define UART_MAXSTRLEN 380
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
[math]\displaystyle{ min Anz = 2\cdot\left(160-\frac{160}8\right)+60+5 = 345 }[/math]
sein, um korrekt Textnachrichten bis zu einer Länge von 160 Zeichen empfangen zu können (60 ist die maximale Größe des PDU Header und 5 eine kleine Reserve für Steuerzeichen wie new line).
Die Nächsten Einstellungen sind in der Headerdatei sms.h vorzunehmen. Hier muss zunächst die Telefonnummer über
/**
* Adressat, an welche SMS geschickt werden soll
* <br> (immer führende 0 mitschreiben, NICHT +49)
*/
#define SMS_TELNR "01623456789"
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
/**
* definiert die maximale Anzahl der Telefonnummern in der Telefonnummernliste
* <br> Dies kann zur Anrufernummernerkennung genutzt werden.Dabei werden immer die ersten \ref SMS_TELNR_LIST_MAX Nummern der SIM-Karte verwendet (siehe \ref sms_init)
*/
#define SMS_TELNR_LIST_MAX 5
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.
/**
* Trennzeichen um Befehle aus empfangenen Textnachrichten zu selektieren
*/
#define SMS_DELIMITER ",;: "
Dies sind die wichtigsten Einstellungen welche vorab überprüft werden müssen.
Nutzung der Funktionen
Neben 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:
/**
* zusammengefasste Auflistung als Rückgabewert der State Machine (\ref sms_state_machine)
*/
typedef enum {
SMS_OK, /**< OK von Mobiltelefon empfangen */
SMS_ERROR, /**< ERROR von Mobiltelefon empgangen */
SMS_MSG_DECODE, /**< Textnachricht eingegangen, decodiert und in \ref SMS_DECODE_DATA_T Struktur gespeichert */
SMS_INCOMING_RING, /**< eingehender Anruf */
SMS_CANCEL_RING, /**< eingehender Anruf wurde abgewiesen */
SMS_REQUEST_TELNR, /**< Telefonnummer des eingehenden Anruft wurde abgefragt */
SMS_RETRIEVE_TELNR, /**< Anrufer wurde abgewiesen, Telefonnummer ermittelt und korrekt mit \ref SMS_TELNR bzw. \ref SMS_TELNR_LIST_T verglichen
- über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */
SMS_RETRIEVE_nTELNR, /**< Anrufer wurde abgewiesen, Telefonnummer ermittelt und <b>nicht</b> korrekt mit \ref SMS_TELNR bzw. \ref
SMS_TELNR_LIST_T verglichen - über \ref sms_last_caller kann jetzt der Anrufer identifiziert werden */
SMS_IDLE /**< empfangene Zeichenkette wurde nicht in sms_state_machine "gefunden" (kein Eintrag) */
} 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:
...
uint8_t flag;
// main loop
while(1){
flag = sms_state_machine();
if (flag == SMS_RETRIEVE_TELNR){
// mache irgend etwas
}
}
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:
/**
* @brief
* Struktur mit Datums- und Zeitangaben einer empfangenen Textnachricht
*/
typedef struct {
uint8_t year; /**< Jahresangabe YY */
uint8_t month; /**< Monatsangabe MM */
uint8_t day; /**< Tagangabe DD */
uint8_t hour; /**< Stundenangabe hh */
uint8_t minute; /**< Minutenangabe mm */
uint8_t second; /**< Sekundenangabe ss */
} DATE_T;
/**
* @brief
* Struktur zum speichern der decodierten Daten aus einer empfangenen Textnachricht
*/
typedef struct {
char nachricht[SMS_MESSAGE_MAX_LEN+1]; /**< decodierte PDU Nachricht */
char telnr[SMS_TELNR_MAX_LEN+1]; /**< Telefonnummer des Absenders */
DATE_T date; /**< Struktur mit Datums- und Zeitelementen (siehe \ref DATE_T) */
} SMS_DECODE_DATA_T;
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.
Download
Software Stand 28.12.2010 (Bug in sms_decode behoben)
Software Stand 08.05.2010
Doxygen Hilfe des Projektes
Eagle Layout des Projektes
AT Command Set For L55 Siemens Mobile Phones And Modems
Länderspezifischer Zeichensatz der Mobiltelefone nach 3GPP 23.038 - Alphabets and language-specific information
Nähere Erläuterungen zu den AT^SSTK Kommandos - Specification of the SIM Application Toolkit (GSM 11.14)
ATMEL Application Note 323 - Interfacing GSM modems
Quellen
Allgmeine Quellen zum Thema
- Online PDU Encoder und Decoder
- SMS and the PDU Format
- SMS PDU Dokumentation
- Siemens Slim Lumberg Steckerbelegung
- 3GPP: Alphabets and language-specific information
- Siemens Mobile: AT Command Set For L55 Siemens Mobile Phones And Modems
- ATMEL: Application Note 323 - Interfacing GSM modems