Die im folgenden beschriebene Applikation
erlaubt es, das Web-IO unter Linux zu steuern Die Bedienoberfläche
wurde mit dem Qt-Designer in Version 3.3.5 zusammengestellt.
Mit dem folgenden C++ Programmbeispiel können Sie Ihr Web-IO Digital
mit seinen Inputs und Outputs in einer
Linux-Anwendung abbilden. Darüber hinaus können Sie die Outputs
des Web-IO schalten.
Sie haben noch kein Web-IO und möchten das vorgestellte Beispiel
einfach mal ausprobieren?
Kein Problem: Wir stellen Ihnen das Web-IO Digital 2xInput, 2xOutput
gerne kostenlos für 30 Tage zu Verfügung. Einfach Musterbestellung
ausfüllen, wir liefern das Web-IO zum Test auf offene Rechnung.
Wenn Sie das Gerät innerhalb von 30 Tagen zurück schicken,
schreiben wir die Rechnung komplett gut.
1. Zusammenstellen der verschiedenen Bedienelemente und Anzeigeobjekte
im Qt-Designer
Um diese Applikation zu erstellen wird im Qt-Designer ein neues C++
Projekt erzeugt dem ein belibieger Name gegeben werden kann. Wir haben
uns hier für "Client" entschieden. Im nächsten Schritt
wird ein Mainwindow erzeugt, in dem die graphischen Elemente platziert
und in deren Eigenschaftenbenannt werden.
Um sich unter einem Unix System das komplieren der Applikation zu
erleichtern, erzeugen wir zwei Dateien namens "Uic" und "Qmake".
So erhalten wir funktionsfähigen C++ Quelltext, denn man mit einem
Makefile problemlos compilieren kann.
Man erstellt eine neue Textdatei und schreibt die beiden folgenden
Zeilen hinein. Daraufhin speichert man die Datei unter "Uic".
Hinweis: Diese Zeilen funktionieren nur insofern qt3 verwendet wird
und es an der selben Stelle im System installiert ist. Sonst bitte die
beiden Zeilen anpassen.
Nun erstellt man noch eine Textdatei, die anschließend unter
"Qmake" gespeichert wird.
/usr/lib/qt3/bin/qmake -o Makefile $1.pro
Sind beide Dateien erstellt, legt man beide in das Verzeichnis, in
dem auch das Projekt liegt. Darauf hin konfiguriert man die beiden Dateien
so, dass sie ausführbar werden. Dafür kann man das chmod Kommando
verwenden.
-> chmod a+x Dateiname
Im folgenden kann das Projekt erfolgreich in C++ Quellcode umgewandelt
und compiliert werden. Dazu sind nur noch drei Schritte notwendig.
./Uic Dateiname(.ui)
./Qmake Projekt(.pro)
make
Nun wurde erfolgreich eine ausführbare Datei erstellt, welche
genauso wie das Projekt heisst.
2. Erstellen der Quellcode Datei der graphischen Oberfäche
Wenn der Qt-Designer gestartet ist und man das Mainwindow geöffnet
vor sich hat, wird durch ein Doppelklick auf das Window eine .ui.h Quellcode
Datei erzeugt. Im folgenden wird Ihnen in einzelnen beschrieben, welche
Schritte notwendig sind um diese Applikation zum laufen zu bekommen.
Um neue Slots zu erzeugen kann man durch einen Rechtsklick auf das
Mainwindow ein Eigenschaften Fenster öffnen und dort den Eintrag
Slots wählen. Dort erzeugt man sich die benötigten Slots,
welche dann mit einem leeren Rumpf automatisch in der erzeugten .ui.h
Datei erscheinen.
Nun includieren wir noch einige benötigte Header-Dateien. Die
clientDlg.h und die clientDlg.cpp werden nach der Anwendung mit ./Uic
aus der .ui Datei (Mainwindow) erzeugt. Um aúf die Elemente zugreifen
zu können wird die Header Datei hier includiert.
Anschließend werden globale Variablen für eine TCP-Verbindung
und das Polling deklariert und somit jeder Methode der Klasse zugänglich
gemacht. Da wir keine eigenen Namensraum definieren, wird der Standardnamensraum
verwendet.
Einrichten der Bedienelemente
Die Gruppe mit den Bedienelementen für das Web-IO wird zunächst
für die Bedienung gesperrt. Sobald eine Verbindung zu Stande kommt,
werden alle benötigten Elemente freigeschalte. Dazu kann man in
den Eigenschaften der GroupBox cb_io_control, sowie bei allen anderen
Elementen, die Enable-Funktion auf 'false' oder 'true' setzen.
Der Name des jeweiligen Bedienelementes ist dem Kontext nach von dem
Element selbst abgeleitet. Die beiden ersten Zeichen im Namen stehen
für den Typ des Elemente (cb -> Checkbox, bt -> Button, gb
-> Groupbox und
le-> LineEdit).
4. Die Verbindungskontrolle
Einleiten der Verbindung
Nach Eingabe der IP-Adresse des Web-IO in das Textfeld le_ip und dem
Port 80 in das Textfeld le_port kann durch Betätigung des Buttons
bt_connect eine Verbindung aufgebaut werden. Falls keine IP-Adresse
oder kein Port eingetragen wird, folgt eine Meldung durch die Applikation
in der Statusleiste.
Verbindungsaufbau
Um eine TCP-Verbindung aufbauen zu können wird die bereits deklarierte
Socketvariable initialisiert.
Ist alles korrekt eingegeben worden beginnt jetzt der Versuch eine Verbindung
zu erzeugen. Um zu erfahren ob die Verbindung auch realisiert worden
ist wird auf ein Signal des Sockets gewartet, welches einen erfolgreichen
Verbindungsaufbau meldet.
void clientDlg::onConnect()
{
client = new QSocket(this);
bool ok;
if(le_ip->text() == "")
le_statusBar->setText("No IP entered!"); else if(le_port->text() == "")
le_statusBar->setText("No port
entered!"); else
client->connectToHost(le_ip->text(),
(le_port->text()).toInt(&ok,10));
}
Im Falle eines Fehlers beim Verbindungsaufbau wird
in der Statusleiste eine Meldung ausgegeben.
void clientDlg::connectError( int
)
{
le_statusBar->setText("Error while connecting!");
}
Verbindung kommt zustande
Nach erfolgreichem Verbindungsaufbau werden alle nützlichen Bedienelemente
der Applikation freigschalten und der Connect Button deaktiviert.
Ausserdem beginnt die Applikation sofort damit, in Empfangsbereitschaft
zu gehen.
Trennen der Verbindung
Die Verbindung bleibt solange bestehen, bis sie vom Benutzer durch
Klick auf den Disconnect-Button oder duch das Web-IO beendet wird.
Nach Betätigung des Buttons wird eine Meldung ausgegeben, dass
die Verbindung beendet wird.
Bei Verbindungsende werden alle Elemente wieder für
die Bedienung gesperrt.
5. Bedienung und Kommunikation von Client-Seite
Sobald eine Verbindung mit dem Web-IO zustande gekommen ist, kann
der Anwender durch Bedienung der entsprechenden Programmelemente Kommandos
an das Web-IO senden
Beim Senden einer Nachricht an das Web-IO wird asynchron
gearbeitet. Dadurch ist die Applikation bei einem Sende-/Empfangsvorgang
nicht blockiert.
Setzen der Outputs
Die Outputs des Web-IO können mit Hilfe der beiden Checkboxen
cb_output0 und cb_output1 geschaltet werden.
Im nächsten Schritt wird geprüft ob die
Checkbox bereits gesetzt ist und entsprechende Output auf ON oder
OFF gesetzt.
Da alle Counterzustände mit einem Kommando
gelesen oder zurückgesetzt werden können, muss noch eine
Methode implementiert werden, welche den Antwortstring des Web-IO
bearbeitet und jedem Counter in der Applikation seinen spezifischen
Zustand zuordnet.
void clientDlg::readAndClearCounter(QString
data)
{ QString counter[12]; int j = 0; int length
= data.length(); for(int
i = 0; i < length; i++) { if(data[i]
== ';') j++; else counter[j]
+= data[i]; } le_counter0->setText(counter[0]); le_counter1->setText(counter[1]);
}
6. Datenempfang vom Web-IO
Auswerten und Anzeigen der empfangenen Daten
Alle Kommandos und Anfragen an das Web-IO werden mit einem Antwort-String
quittiert. Dabei haben die Antworten je nach Type einen spezifischen
Aufbau:
Für die Outputs: output;<Binärwert des Outputstatus im
hexadezimalen Format>
Für einen speziellen Output: outputx;<ON oder OFF>
Für die Inputs: input;<Binärwert des Outputstatus im hexadezimalen
Format>
Für einen speziellen Input: inputx;<ON oder OFF>
Dann gibt es noch den Antwortstring für einen Counter der folgendermassen
aussieht.
Counter: counterx;<dezimaler Zählerstand>
oder counter;<dezimaler Zählerstand 0 >; <dezimaler Zählerstand
0 >; ... wenn alle Counter auf einmal gelesen werden sollen.
Alle Antwort-Strings sind mit einem 0-Byte abgeschlossen.
In unserer Applikation wird zum Empfang einer solchen Nachricht die
Methode onReceive() aufgerufen. In dieser Methode wird der Antwortstring
empfangen und verarbeitet. Das besondere ist hier, dass sich diese Funktion
die ganze Zeit selbst aufruft und somit ununterbrochen nach Nachrichten
schaut, welche möglicherweise vom Web-IO gesendet worden sind.
Festgelegt haben wir dass ja direkt nach dem eine Verbindung erfolgreich
initialisiert worden ist (connectDone()).
Zyklisches Abfragen bestimmter Werte
Es ist wünschenwert, dass sich der Status einer einzelnen Komponente
von selbst aktualisiert. Dazu wird in diesem Progamm ein Timer verwendet,
der in einem vom User betimmten Zeitintervall zyklisch Abfragen an das
Web-IO sendet.
Due Zykluszeit wird in das Feld le_interval eingegeben.
Natürlich wird auch abgefangen falls der Nutzer eine unsinnige
Angabe, wie z.B. einen negativer Zeitwert macht. Darauf folgt sofort
eine Meldung und der Wert wird nicht übernommen.
bool clientDlg::checkRange()
{ bool ok; int tmp = (le_interval->text()).toInt(&ok,
10); if(ok &&
tmp > 0) { le_statusBar->setText("Range
changed to " + le_interval->text() + " ms!"); returntrue; } else { le_statusBar->setText("Please
type a positive integer value for the range of polling!"); returnfalse; }
}
Um nun auch das zyklische Abfragen der Zustände
des Web-IO durchzuführen, was auch als Polling bezeichnet wird,
besteht die Auswahlmöglichkeit zwischen dem Polling der Outputs,
der Inputs oder der Counter.
Betätigt man die Checkbox cb_polling_outputs so wird das Polling
auf die Outputs angewendet.
Es wurden drei verschiedene Timer initialisiert, die
im eingetragenen Intervall eine Aktion auslösen. Um die Events
zu fangen muss noch eine Methode implementiert werden.
Das Beispiel Programm
unterstützt alle gängigen Funktionen des Web-IO im Kommando-String
Modus, optimiert für das Web-IO
2x Digital Input, 2x Digital Output. Für die anderen Web-IO Modelle
müssen ggf. Anpassung am Programm vorgenommen werden. Weitere Programmbeispiele
zur Socket-Programmierung finden Sie auf den Tool-Seiten
zum Web-IO. Eine Detaillierte Beschreibung zur Socketschnittstelle der
Web-IO Digital Modelle finden Sie im Referenzhandbuch.