Dieses Modul hat die Aufgabe, die vom Modem an den Computer gesendeten Strings zu interpretieren und einerseits dem Modem, falls nötig, zu antworten, andererseites aber auch das Hauptmodul durch entsprechende Signale von den erhaltenen Informationen in Kenntnis zu setzen.
#ifndef __modeminterpreter_h
#define __modeminterpreter_h
#include <qobject.h>
#include <string.h>
#include <ctype.h>
#include "sercomm.h"
class ModemInterpreter: public QObject
{
Q_OBJECT
public:
ModemInterpreter (SerComm *ser, QObject *parent = NULL,
const char *name = NULL);
~ModemInterpreter () {}
private:
SerComm *serial;
char *sender,
pos[5],
antworten;
int expectSMS;
signals:
void strauch (bool);
void rasen (bool);
void blumen (bool);
void biotop (bool);
void automatic ();
public slots:
void fromModem (char*);
};
#endif
#include "modeminterpreter.h"
#include <stdio.h>
#include "mainform.h"
#include "definitionen.h"
#define CTRL_Z 0x1A
ModemInterpreter::ModemInterpreter (SerComm *ser, QObject *parent, const char *name)
:QObject (parent, name), expectSMS (SMS_EXPECTNULL)
{
serial = ser;
connect (ser, SIGNAL(gotLine(char*)), this, SLOT(fromModem(char*)));
}
void ModemInterpreter::fromModem (char *line)
{
char buff[100];
if (strlen(line) > 0)
{
for (int i = 0; i < strlen(line); i++)
line[i] = toupper(line[i]);
if (strstr(line, "RING") != NULL)
serial->sendCommand ("AT+CHUP\r");
else if (strstr (line, "+CMTI:") != NULL)
{
expectSMS = SMS_EXPECTHEAD;
sprintf (pos, "%s", strchr(line, ',') + 2);
sprintf (buff, "AT+CMGR=%s\r", pos);
serial->sendCommand (buff);
}
else if (strstr (line, "+CMGR:") != NULL)
{
if (strstr (line, NUMMER1) != NULL)
{
sender = NUMMER1;
expectSMS = SMS_EXPECTDATA;
}
else if (strstr (line, NUMMER2) != NULL)
{
sender = NUMMER2;
expectSMS = SMS_EXPECTDATA;
}
else
{
sprintf (buff, "SMS von unbekanntem Absender >%s< erhalten.", strchr(line, ':') + 2);
((Konsole*)parent())->writeLog (buff);
sender = NULL;
expectSMS = SMS_IGNOREDATA;
}
}
else if (expectSMS == SMS_SENDHEADING && strstr (line, "OK") != NULL)
{
sprintf (buff, "AT+CMGS=\"%s\"\r", sender);
serial->sendCommand (buff);
expectSMS = SMS_EXPECTPROMPT;
}
else if (expectSMS == SMS_EXPECTDATA)
{
if (strstr (line, "OK") != NULL)
{
sprintf (buff, "AT+CMGD=%s\r", pos);
serial->sendCommand(buff);
if (antworten)
{
expectSMS = SMS_SENDHEADING;
antworten = 0;
}
else
expectSMS = SMS_EXPECTNULL;
}
else
{
if (strstr (line, "BIOTOP AUS") != NULL)
emit biotop (FALSE);
if (strstr (line, "RASEN EIN") != NULL)
emit rasen (TRUE);
if (strstr (line, "RASEN AUS") != NULL)
emit rasen (FALSE);
if (strstr (line, "BLUMEN EIN") != NULL)
emit blumen (TRUE);
if (strstr (line, "BLUMEN AUS") != NULL)
emit blumen (FALSE);
if (strstr (line, "STRAUCH EIN") != NULL)
emit strauch (TRUE);
if (strstr (line, "STRAUCH AUS") != NULL)
emit strauch (FALSE);
if (strstr (line, "BIOTOP EIN") != NULL)
emit biotop (TRUE);
if (strstr (line, "AUTOMATIK") != NULL)
emit automatic();
if (strstr (line, "STATUS") != NULL)
antworten = 1;
}
}
else if (strstr (line, ">") != NULL && expectSMS == SMS_EXPECTPROMPT)
{
int s_rasen, s_blumen, s_strauch, s_biotop, s_auto, s_regen;
((Konsole*)parent())->getStatus (&s_rasen, &s_blumen, &s_strauch,
&s_biotop, &s_auto, &s_regen);
sprintf (buff,"Rasen %s + Blumen %s + Strauch %s + Biotop %s + Automatik %s + %s%c\r",
(s_rasen) ? "ein" : "aus",
(s_blumen) ? "ein" : "aus",
(s_strauch) ? "ein" : "aus",
(s_biotop) ? "ein" : "aus",
(s_auto) ? "ein" : "aus",
(s_regen) ? "Regen" : "kein Regen",
CTRL_Z);
serial->sendCommand (buff);
expectSMS = SMS_IGNORENEXT;
}
else if (expectSMS == SMS_IGNOREDATA && strstr (line, "OK") != NULL)
{
expectSMS = SMS_EXPECTNULL;
sprintf (buff, "AT+CMGD=%s\r", pos);
serial->sendCommand (buff);
}
else if (expectSMS == SMS_IGNORENEXT)
expectSMS = SMS_EXPECTNULL;
}
}
Im Konstruktor des Objekts wird ein Zeiger auf das vorhandene Modul zur Kommunikation mit der seriellen Schnittstelle gespeichert und das Signal gotLine(char*) des Kommunikationsmoduls mit dem internen fromModem(char*) - Slot verbunden.
Der Slot fromModem hat die Aufgabe, die erhaltenen Strings zu interpretieren und auf die interpretierten Daten zu reagieren. Um dabei auf hintereinander folgende Strings, die zusammenhängen, richtig zu reagieren, kennt die Methode mehrere Zustände, die in der folgenden Tabelle kurz erklärt sind.
| Zustand | Bedeutung |
|---|---|
| SMS_EXPECTNULL | Dieser Zustand bedeutet, dass zuletzt kein String empfangen wurde, aufgrund dessen der nächste erhaltene String speziell interpretiert werden muss. |
| SMS_EXPECTHEAD | Der nächste String, der erhalten wird, ist die Kopfzeile einer SMS. |
| SMS_EXPECTDATA | Wenn der nachfolgene String nicht "OK" enthält, was das Ende der Daten bedeuten würde, stellt die erhaltene Zeile den Inhalt einer SMS dar. |
| SMS_IGNOREDATA | Dieser Status bedeutet, dass die Zeilen, die erhalten werden, bis zur nächsten Zeile mit "OK" der Inhalt einer SMS von einem unbekannten Absender sind. Sie sollen deshalb ignoriert werden. |
| SMS_IGNORENEXT | Die nächste erhaltene Zeile wird ignoriert, danach wird in den SMS_EXPECTNULL - Status gewechselt. Dieser Status wird beim Senden einer SMS benötigt, um nicht auf das Echo des Modems zu reagieren. |
| SMS_SENDHEADING | Sobald der vorhergehende Befehl abgeschlossen ist, soll der Kopf einer SMS an das Modem gesendet werden. |
| SMS_EXPECTPROMPT | In diesem Status wird gewartet, bis das Modem ein > - Zeichen sendet. Anschließend wird der Text für ein SMS an das Modem geschickt. |
Wenn sich die Anlage im SMS_EXPECTNULL - Status befindet, reagiert sie auf empfangene Strings wie folgt.
| Empfangener String | Bedeutung | Reaktion |
|---|---|---|
| RING | Das Modem wird angerufen. | Der Befehl AT+CHUP wird zum Modem gesendet, dadurch wird der Anruf unterbrochen. |
| +CMTI: ... | Eine Nachricht ist angekommen. | Das Interpretationsmodul wechselt in den SMS_EXPECTHEAD - Status. |
| andere Werte | ??? | keine |
Im SMS_EXPECTHEAD - Status wartet die Methode auf einen String, der die Zeichenkette "+CMGR: ..." enthält. Dies ist der Beginn eines Kopfs einer SMS. Aus dem Kopf wird die Absendernummer kopiert und mit zwei gespeicherten Nummern verglichen. Wenn der Absender eine der zwei angegebenen Nummern hat, wechselt die Anlage in den SMS_EXPECTDATA - Status, um auf den folgenden Text reagieren zu können. Anderenfalls wird in den SMS_IGNOREDATA - Zustand gewechselt, um die ankommenden Daten zu ignorieren.
Im SMS_EXPECTDATA - Modus werden alle erhaltenen Strings bis zum abschließenden "OK" - String auf die folgenden Inhalte geprüft.
| Inhalt | Bedeutung |
|---|---|
| BIOTOP AUS | Die Bewässerung des Biotops wird ausgeschaltet. |
| RASEN EIN | Die Rasenbewässerung wird eingeschaltet. |
| RASEN AUS | Die Rasenbewässerung wird ausgeschaltet. |
| BLUMEN EIN | Die Bewässerung des Blumenbeets wird eingeschaltet. |
| BLUMEN AUS | Die Bewässerung des Blumenbeets wird ausgeschaltet. |
| STRAUCH EIN | Die Sträucher werden bewässert. |
| STRAUCH AUS | Die Sträucher werden nicht mehr bewässert. |
| BIOTOP EIN | Die Bewässerung des Biotops wird eingeschaltet. |
| AUTOMATIK | Die Anlage soll in den Automatikstatus wechseln. |
| STATUS | Eine Mitteilung mit dem aktuellen Status der Anlage wird an den Sender zurückgeschickt. |
Beim Interpretieren der empfangenen Daten ist es wichtig, dass zu Beginn überprüft wird, ob die Bewässerung des Biotops aus- und erst am Ende kontrolliert, ob sie eingeschaltet werden soll. Wird das Biotop nämlich bewässert, so können keine anderen Zonen bewässert werden und umgekehrt.