Das Kommunikationsmodul für die serielle Schnittstelle hat die Aufgabe, die Kommunikation mit dem Modem zu realisieren. Es muss Strings zum Modem schicken können. Empfangene Zeichen sollen zu einem String zusammengesetzt und erst dann an das Interpretationsmodul weitergereicht werden, wenn der komplette String empfangen wurde.
#ifndef __sercomm_h
#define __sercomm_h
#include <qobject.h>
#include <string.h>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include <qsocketnotifier.h>
#include "definitionen.h"
class SerComm: public QObject
{
Q_OBJECT
public:
SerComm (int port, QWidget *main, QObject *parent = NULL, const char *name = NULL);
~SerComm ();
void sendCommand (char*);
private:
int serport, inbuff_wr;
char inbuff[300];
QSocketNotifier *notifier;
struct termios serial_ori;
signals:
void gotLine (char*);
private slots:
void dataReady ();
};
#endif
#include "sercomm.h"
#include <stdio.h>
#include <errno.h>
#include "pinform.h"
#define SPEED B19200
SerComm::SerComm (int port, QObject *parent, const char *name)
:QObject (parent, name), serport (-1), inbuff_wr (0)
{
int i;
struct termios serterm;
if ((serport = open ((port == SER1) ? "/dev/ttyS0" : "/dev/ttyS1", O_RDWR)) < 0)
{
perror ("Fehler beim Öffnen der seriellen Schnittstelle");
exit (-1);
}
tcgetattr (serport, &serterm);
serial_ori = serterm;
serterm.c_lflag &= ~ICANON;
serterm.c_lflag &= ~(ECHO|ECHOCTL|ECHONL);
serterm.c_lflag |= HUPCL;
serterm.c_cc[VMIN] = 1;
serterm.c_cc[VTIME] = 0;
serterm.c_oflag &= ~ONLCR;
serterm.c_iflag &= ~ICRNL;
cfsetospeed (&serterm, SPEED);
cfsetispeed (&serterm, SPEED);
tcsetattr (serport, TCSANOW, &serterm);
strcpy (inbuff, "AT+CPIN?\r");
write (serport, inbuff, 9);
for (i = 0; i < 9; i++)
read (serport, inbuff, 1);
i = 0;
do {
read (serport, inbuff+i, 1);
++i;
} while (inbuff[i-1] != 0x0A);
inbuff[i-1] = 0x00;
if (strstr (inbuff, "+CPIN: READY") != NULL)
{
strcat (inbuff, " eingeben");
PinForm *pf = new PinForm (inbuff+7);
pf->exec();
sprintf (inbuff, "AT+CPIN=%s\r", pf->getPIN());
write (serport, inbuff, strlen(inbuff));
for (i = 0; i < strlen(inbuff); i++)
read (serport, inbuff+20, 1);
i = 0;
do {
read (serport, inbuff+i, 1);
++i;
} while (inbuff[i-1] != 0x0A);
inbuff[i-1] = 0x00;
if (strstr(inbuff, "OK") == NULL)
{
printf ("PIN war ungültig.\n");
exit (-2);
}
}
strcpy (inbuff, "AT+CMGF=1\r");
write (serport, inbuff, strlen(inbuff));
for (i = 0; i < strlen(inbuff); i++)
read (serport, inbuff, 1);
notifier = new QSocketNotifier (serport, QSocketNotifier::Read, NULL);
connect (notifier, SIGNAL(activated(int)), this, SLOT(dataReady()));
notifier->setEnabled(TRUE);
}
SerComm::~SerComm ()
{
tcsetattr (serport, TCSANOW, &serial_ori);
close (serport);
}
void SerComm::dataReady ()
{
char c;
read (serport, &c, 1);
if (c != 0x0A && c != 0x0D)
inbuff[inbuff_wr++] = c;
if (c == 0x0A || c == '>')
{
inbuff[inbuff_wr] = 0x00;
inbuff_wr = 0;
emit gotLine (inbuff);
}
}
void SerComm::sendCommand (char *command)
{
char c;
write (serport, command, strlen(command));
}
Im Konstruktor wird das serielle Terminal konfiguriert, nachgefragt, ob ein PIN nötig ist und eventuell ein Fenster zum Eingeben des PINs angezeigt und das Nachrichtenformat eingestellt. Anschließend wird der Dateideskriptor der Schnittstelle mit einem QSocketNotifier verbunden, der ein Signal aussendet, sobald Daten zum Lesen an der Schnittstelle angelangt sind. Dadurch ist es möglich, nur dann zu versuchen, Daten zu lesen, wenn auch wirklich Daten angekommen sind. So kann die Oberfläche blockierungsfrei gehalten werden.
Der Destruktor stellt die ursprünglichen Einstellungen der seriellen Schnittstelle wieder her und schließt den Dateideskriptor für die Schnittstelle.
Die Methode sendCommand schickt den ihr übergebenen String an das Modem weiter.
Der Slot dataReady wird vom QSocketNotifier aktiviert. Es wird ein Zeichen von der Schnittstelle gelesen und in einen Puffer geschrieben. Anschließend wird kontrolliert, ob das erhaltene Zeichen den String abschließt. Ist dies der Fall, so wird das Signal gotLine ausgesendet, in dem der Inhalt des Puffers weitergegeben wird.