W&T Interfaces
für TCP/IP, Ethernet, RS-232, RS-485, USB, 20mA
Glas- und Kunststoff-LWL, http, SNMP, OPC, I/O digital, I/O analog, ISA, PCI, ...?
      Produkte
Home Kontakt   Distributoren weltweit
Sprachen:
DE

US

ES

IT

RU
Web-IO Universal
Digital
Analog
Web-IO Anwendungsfertig
Klima überwachen
Alarmmeldezentrale
Web-Count / S0-Erfassung
IP-Überwachung
Datenserver
Motherbox 2
pure.box 2
Netzwerkspeicher
TCP/IP-Ethernet Server
Com-Server (Seriell)
USB-Server
Serielle Interfaces
USB, RS232, RS485, 20mA
Isolatoren & Lichtleiter
USB, RS232, RS485, 20mA
PC-Karten
PCI Express, PCI- und
ISA-Bus
...
Drucker-Interfaces
Kundenfrequenzmessung

Zubehör
Downloads
Altes
Warenkorb    Ihr Warenkorb

 
      Fachwissen
Bücher, Aufsätze, Glossare...
Technische Hintergrundinfo
Applikationen zu Com-Server,
USB-Server
, Web-IO,
Web-Thermometer,
Motherbox und pure.box
 
Applikation zum Web-IO Digital:

Web-IO Digital mit C++ unter Linux steuern und überwachen




 Weiterführende Links: Produktübersicht Applikationsübersicht Druck-Version


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.

Web-IO unter Linux


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.

Zur Musterbestellung   Zur Musterbestellung  

Vorbereitungen
Sie haben Ihr Web-IO Digital bereits
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.

    /usr/lib/qt3/bin/uic $1.ui -o $1.h
    /usr/lib/qt3/bin/uic -impl $1.h $1.ui -o $1.cpp

  • 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.

    #include "clientDlg.h"
    #include <qsocket.h>
    #include <qstring.h>
    #include <qtextstream.h>
    #include <qtimer.h>
    #include <iostream>

  • 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.



    using namespace std;

    QSocket* client;
    QTimer* output;
    QTimer* input;
    QTimer* counter;

3. Programmstart
  • 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;

  connect(client, SIGNAL(connected()), SLOT(connectDone()));
  connect(client, SIGNAL(error(int)), SLOT(connectError(int)));

  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.

    void clientDlg::connectDone()
    {
      le_statusBar->setText("Connected to " + le_ip->text());
      connect(client, SIGNAL(readyRead()), SLOT(onReceive()));

      output = new QTimer(this);
      connect(output, SIGNAL(timeout()), SLOT(timerEvent()));

      input = new QTimer(this);
      connect(input, SIGNAL(timeout()), SLOT(timerEvent()));

      counter = new QTimer(this);
      connect(counter, SIGNAL(timeout()), SLOT(timerEvent()));

      gb_io_control->setEnabled(true);
      bt_disconnect->setEnabled(true);
      bt_connect->setEnabled(false);
    }



  • 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.
void clientDlg::onDisconnect()
{
  client->close();

  output->stop();
  input->stop();
  counter->stop();

  gb_io_control->setEnabled(false);
  bt_disconnect->setEnabled(false);
  bt_connect->setEnabled(true);
  le_statusBar->setText("Disconnected!");
}

 

  • 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.

void clientDlg::onOutput0()
{
  QString message1 = "GET /outputaccess0?PW=" + le_password->text() + "&State=ON&";
  QString message2 = "GET /outputaccess0?PW=" + le_password->text() + "&State=OFF&";

  if(cb_output0->isChecked()) client->writeBlock(message1, message1.length());
  else                        client->writeBlock(message2, message2.length());

  client->flush();
}


void clientDlg::onOutput1()
{
  QString message1 = "GET /outputaccess1?PW=" + le_password->text() + "&State=ON&";
  QString message2 = "GET /outputaccess1?PW=" + le_password->text() + "&State=OFF&";

  if(cb_output1->isChecked()) client->writeBlock(message1, message1.length());
  else                        client->writeBlock(message2, message2.length());

  client->flush();
}

  • Output/Input-Status abfragen
void clientDlg::onReadallOutputs()
{
  QString message = "GET /output?PW=" + le_password->text() + "&";
  client->writeBlock(message, message.length());
  client->flush();
}
void clientDlg::onReadallInputs()
{
  QString message = "GET /input?PW=" + le_password->text() + "&";
  client->writeBlock(message, message.length());
  client->flush();
}
  • Counter abfragen

void clientDlg::onReadCounter0()
{
QString message = "GET /counter0?PW=" + le_password->text() + "&";
client->writeBlock(message, message.length());
client->flush();
}

void clientDlg::onReadCounter1()
{
QString message = "GET /counter1?PW=" + le_password->text() + "&";
client->writeBlock(message, message.length());
client->flush();
}

  • Natürlich können alle Counterzustände auch mit einem Kommando abgefragt werden.

    void clientDlg::onReadallCounter()
    {
    QString message = "GET /counter?PW=" + le_password->text() + "&";
    client->writeBlock(message, message.length());
    client->flush();
    }


  • Counter zurücksetzen
    Es ist außerdem möglich, die Zähler nach dem Lesen auf 0 zu setzen.
void clientDlg::onClearCounter0()
{
QString message = "GET /counterclear0?PW=" + le_password->text() + "&";
client->writeBlock(message, message.length());
client->flush();
}
void clientDlg::onClearCounter1()
{
QString message = "GET /counterclear1?PW=" + le_password->text() + "&";
client->writeBlock(message, message.length());
client->flush();
}

  • Natürlich lassen sich auch alle Counter zusammen mit einem Kommando zurücksetzen.

    void clientDlg::onClearallCounter()
    {
    QString message = "GET /counterclear?PW=" + le_password->text() + "&";
    client->writeBlock(message, message.length());
    client->flush();
    }

  • 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()).
void clientDlg::onReceive()
{
  char buffer[50];
  client->readBlock(buffer, 49);
  QString rcv = buffer;
  bool ok;

  if(rcv[0] == 'o')
  {
    int value = rcv.right(rcv.length()-7).toInt(&ok, 16);
    if((value & 1) == 1) cb_output0->setChecked(true);
    else                 cb_output0->setChecked(false);
    if((value & 2) == 2) cb_output1->setChecked(true);
    else                 cb_output1->setChecked(false);
  }
  if(rcv[0] == 'i')
  {
    int value = rcv.right(rcv.length()-6).toInt(&ok, 16);
    if((value & 1) == 1) cb_input0->setChecked(true);
    else                 cb_input0->setChecked(false);
    if((value & 2) == 2) cb_input1->setChecked(true);
    else                 cb_input1->setChecked(false);
  }
  if(rcv[0] == 'c')
  {
    if(rcv[7] == '0') le_counter0->setText(rcv.right(rcv.length()-9));
    if(rcv[7] == '1') le_counter1->setText(rcv.right(rcv.length()-9));
    if(rcv[7] == ';') readAndClearCounter(rcv.right(rcv.length()-8));
  }
}

 
7. Polling
  • 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!");
    return true;
  }
  else
  {
    le_statusBar->setText("Please type a positive integer value for the range of                            polling!");
    return false;
  }
}
  • 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.

    void clientDlg::onPollingOutputs()
    {
      if(checkRange())
      {
        if(cb_polling_outputs->isChecked())
          output->start((le_interval->text()).toInt(), false);
        else
          output->stop();
      }
    }
  • Beim Betätigen der Checkbox cb_polling_inputs wird das Polling auf die Inputs angewendet.
void clientDlg::onPollingInputs()
{
  if(checkRange())
  {
    if(cb_polling_inputs->isChecked())
      input->start((le_interval->text()).toInt(), false);
    else
      input->stop();
  }
}
  • Sollen nun auch noch die Counter unter Polling abgefragt werden, so kann man dazu die Checkbox cb_polling_counter verwenden.
void clientDlg::onPollingCounter()
{
  if(checkRange())
  {
    if(cb_polling_counter->isChecked())
      counter->start((le_interval->text()).toInt(), false);
    else
      counter->stop();
  }
}
  • 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.
void clientDlg::timerEvent()
{
  if(output->isActive()) onReadallOutputs();
  if(input->isActive()) onReadallInputs();
  if(counter->isActive()) onReadallCounter();
}

 

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.

Zur Musterbestellung   Zur Musterbestellung Programmbeispiel herunterladen   Zum Download

 
    Weitere Applikationsbeispiele für Web-IO Digital
Webtechniken
     
     
     
     
  Eigene Webseiten
       
        PHP und AJAX - dynamische Webseiten auch für mehrere Web-IO
        Mashup Webseiten - Werteanzeige in Google Maps Landkarten
        Java-Applet - das integrierte Applet nutzen
        Java-Applet - Beispiel: Anzeige der In- und Outputs
        Java-Applet - Beispiel: Anzeige der In- und Outputs und Steuerung der Outputs
        Java-Applet - Beispiel: Anzeige der Counter
        Java-Applet - Beispiel: Türen öffnen und Lichter schalten im Browser
        Web-IO mit iPhone - visualisieren und steuern
        Web-IO mit iPhone Beispiel: Rolladensteuerung
        Web-IO mit iPhone Beispiel: Klimaüberwachung
        Web-IO mit iPhone Beispiel: Messwertanzeige
Systemintegration
     
     
     
     
     
      Box-to-Box
Datenerfassung
     
      FTP-Datenlogger - Beispiel
Zeitschaltuhr
     
      CRON Zeitschaltuhr (Linux)
      Taskplaner als Zeitschaltuhr
Individual-Programmierung
     
      Visual Basic.Net 2005/2008/2010
      Visual Basic.Net 2005/2008/2010 mit WuTdevice.dll
      Visual C++
      Visual C#
      Visual C# mit WuTdevice.dll
      Visual C++ (Linux mit QT-Designer)
      Visual Delphi
      Visual Delphi.Net (2005)
      Lazarus / FreePascal
      Java
      mit VBScript steuern
Web-IO System
     
     
      Motherbox - mehrere Web-IO ansprechen
      Motherbox - Web-IOs logisch verknüpfen
      Grenzwertüberwachung
  Web-IO - Möglichkeiten der Netzwerkanbindung
       
        DSL
        UMTS/GPRS/Mobilfunknetz
        Satelitenfunk

 
  • Mister Wong
  • Google Bookmarks
  • Twitter
  • Facebook
  • Digg
   Impressum
Wir sind gerne persönlich für Sie da! Wiesemann & Theis GmbH Tel.: 0202/2680-110 (Mo-Fr. 8-17 Uhr)
Porschestr. 12 Fax: 0202/2680-265
42279 Wuppertal individuelle E-Mail

© Wiesemann & Theis GmbH, Irrtum und Änderungen vorbehalten: Da wir Fehler machen können, darf keine unserer Aussagen ungeprüft verwendet werden. Bitte melden Sie uns alle Ihnen bekannt gewordenen Irrtümer oder Mißverständlichkeiten, damit wir diese so schnell wie möglich erkennen und beseitigen können.