Python exemplarisch - RPi Tutorial
deutsch     english

WEB-HOSTS

 

Alle Programme können von hier heruntergeladen werden.


 

Speichern und Abrufen von Daten im Internet

 

Wie Sie in diesem Tutorial gesehen haben, ist der Raspberry Pi eine wunderbare Maschine, um Daten von verschiedenen Sensoren zu erfassen, zum Beispiel Temperatur, Feuchtigkeit, GPS-Koordinaten, oder den Zustand eines Überwachungssystems. Manchmal verabeitet man diese Daten sofort, aber in vielen Anwendungen werden die Daten gespeichert und später, eventuell auf einem anderen System, weiter verarbeitet. Zur lokalen Datenspeicherung kann eine Datei auf der SD-Karte verwendet werden. Die Daten müssen dann später manuell von der SD-Karte, beispielsweise über einen SFTP-Verbindung, ausgelesen werden. Sie haben auch gelernt, wie man Daten in Echtzeit mit der Client/Server-Technologie übertragen kann.

Eine andere interessante Möglichkeit besteht darin, die Daten in einer Online-Datenbank zu speichern, so dass sie mit einem Webbrowser auf einem beliebigen Gerät (PC, Tablet, Smartphone) von überall her abrufbar sind. Dabei kann man sie beliebig in eine Webpage einbauen und sogar eine grafische Darstellung verwenden. In diesem Kapitel lernen Sie, wie man eine solche Anwendung realisiert. Die Ausführungen können auch als Einführung in die Programmierung von dynamischen Webseiten gelesen werden.

In der Regel ist der Datenfluss bei dynamischen Webapplikationen der Folgende:

Datenspeicherung:

  • Der Webserver präsentiert eine Webseite, die ein PHP-Skript enthält, das Daten in einer Online-Datenbank speichern kann
  • Um die Daten in der Datenbank zu speichern, führt der Client einen HTTP-GET-Request aus, in dem die Daten als URL-Parameter codiert sind
  • Der Webserver extrahiert die Parameter und übergibt die Informationen an das PHP-Skript
  • Das Skript erstellt eine Verbindung zum Datenbankserver (auf der gleichen Hardware oder auf einer anderen Maschine) und fügt die Daten mit einem SQL-Befehl in eine Datenbank-Tabelle ein

Datenabfrage:

  • Um die gespeicherten Daten anzuzeigen, wird ein anderes PHP-Script mit einer HTTP-GET-Anfrage aufgerufen
  • Das Skript erstellt wiederum eine Datenbank-Verbindung und ruft mit einem SQL-Befehl Informationen aus der Datenbanktabelle ab
  • Der Webserver integriert die Informationen mit Layout-Tags und sendet die HTML-Datei an den Web-Browser, der sie darstellt
wewbserver1
Die Internetverbindung des Raspberry Pi kann über Ethernet, WiFi oder GSM hergestellt werden. Mit GSM ergibt sich ein elegantes und völlig autonomes Datenerfassungssystem.


 

Zugang bei einem kostenlosem Internet-Service-Provider (ISP)

 

Sie benötigen einen ISP, der Webspace mit PHP, MySQL und (wenig) Speicherplatz anbietet. Wenn Sie keinen Webspace haben, suchen Sie einen ISP, der wenig kostet, oder sogar einen Gratiszugang anbietet. Wir empfehlen awardspace.com, ein kostenloser ISP mit allen Hosting-Funktionen, die Sie benötigen, um Ihre Daten zu speichern und abzurufen. Ein Gratiskonto richten Sie wie folgt ein:

  • Gehen Sie auf www.awardspace.com und klicken Sie auf Free Web Hosting
  • Verwenden Sie auf der nächsten Seite die Standardwerte und drücken Sie CONTINUE
  • Auf der nächsten Seite wählen Sie New Client
  • Klicken Sie auf login into your account. Warten Sie auf das Email mit den Aktivierungsangaben und aktivieren Sie Ihr Konto
  • Als nächstes müssen Sie wie folgt einen Domain-Namen registrieren:

    webserver2
    Wählen Sie eine kostenlose Domain xxx.dx.am und entfernen Sie alle anderen Hosting-Pläne (xxx ist Ihr persönlicher Subdomain-Name)

  • Loggen Sie sich mit FTP ein:
    Server: die registrierte Domain xxx.dx.am
    Username: Ihre E-Mail-Adresse
    Password: das Gleiche wie bei Ihrem Web-Account
    Erstellen Sie eine HTML-Datei mit dem Namen index.html mit einigen einfachen Tags z.B.

    <html>
    <body>
    <h1>Gruss aus dem Paradies</h1>
    </body>
    </html>

    und kopieren Sie diese via FTP in das Unterverzeichnis xxx.dx.am (die Management-Seite bietet auch die Möglichkeit, mit einem Online-Dateibrowser Dateien zu erstellen und zu editieren)

  • Starten Sie einen Web-Browser (ev. müssen Sie den Browser-Cache löschen). Wählen Sie die URL www.xxx.dx.am. Die Website sollte angezeigt werden

  • Loggen Sie sich über http://www.awardspace.com/login in Ihrem Konto ein und klicken Sie auf das Symbol Database Manager im Abschnitt Advanced Tools. Erstellen Sie eine MySQL-Datenbank mit dem angezeigten Datenbanknamen und wählen Sie ein Passwort

    webserver3

  • Unten auf der Seite sehen Sie, dass die Datenbank erstellt wurde. Unter Management / phpMyAdmin 4 entnehmen Sie den Benutzernamen, Host und Port. Notieren Sie sich diese Angaben zum weiteren Gebrauch

    webserver4

    Erstellen Sie die Tabelle temperature wie folgt: Klicken Sie den SQL Tab und geben Sie (event. mit Kopieren und Einfügen) den folgenden SQL-Befehl ein und klicken Sie auf OK

    CREATE TABLE temperature (
    id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
    x VARCHAR(50) NOT NULL,
    y VARCHAR(50) NOT NULL,
    UNIQUE KEY (id)
    ) ENGINE = MYISAM;


  • Erstellen Sie eine Textdatei mit dem unten stehenden PHP-Code und speichern Sie diese als insert.php. in Ihrem Webspace (Verzeichnis, in dem sich bereits index.html befindet).
<?php
echo "Executing: insert.php";
$con= mysqli_connect("host", "username", 
"password", "database_name", "port");
$x = $_GET["x"];
$y = $_GET["y"];
echo "<br>x = ".$x." y =".$y;
$sql ="INSERT INTO temperature (x, y) VALUES ('$x', '$y')";
mysqli_query($con, $sql); 
mysqli_close($con);
echo "<br>done";
?>

Ersetzen Sie host, username, password, database_name, port mit Ihren notierten Daten, beispielsweise:

mysqli_connect("fdb12.awardspace.net", "2188329_raspi",
"UltraSlim", "2188329_raspi", "3306"); 

  • Testen Sie das Einfügen von Daten mit einem Browser. Geben Sie dazu die nachfolgende URL (mit Ihrem xxx) ein. (Sie können dies auch mehrmals mit geänderten Werte für x und y tun.)
    http://www.xxx.dx.am/insert.php?x=1&y=44
    Wenn Sie keine Fehlermeldung erhalten, ist es fast sicher, dass alles bestens funktioniert. Sie können mit phpMyAdmin prüfen, ob die Tabelle temperature die Datensätze enthält (oder Sie sehen es in der nächsten Aktion)

  • Um den Inhalte der Tabelle mit Ihrem Web-Browser abzurufen, erstellen Sie ein Script showall.php und kopieren es in Ihren Webspace (verwenden Sie für $con die gleiche Zeile wie oben).

Programm:

<?php
$con= mysqli_connect("host", "username",
                     "password", "database_name", "port");
$sql = "SELECT * FROM temperature";
$rs = mysqli_query($con, $sql);
$totalRows_rs = mysqli_num_rows($rs);
?>
<html>
<body>
<h1>This is the content of table 'temperature'</h1>
<?php
while ($row = mysqli_fetch_assoc($rs))
{?>
x = <?php echo $row['x'];?> <br>
y = <?php echo $row['y'];?> <br><br>
<?php } ?>
<p>Number of records: <?php echo $totalRows_rs ?></p>
</body>
</html>
<?php
mysqli_free_result($rs);
mysqli_close($con);
?>
  • Mit der URL http://www.xxx.dx.am/showall.php werden alle Datensätze der Tabelle temperature in Ihrem Browser angezeigt

 

Datensätze vom Raspberry Pi in eine Web-Datenbank einfügen

 

Ziel:
Mit einem Python-Programm einige Wertepaare x, y, zum Beispiel die Zahlen 1 bis 5 und deren Quadrate, in einer Web-Datenbank speichern.

Sie haben gesehen, wie man auf eine Web-Datenbank mit PHP und einem Browser zugreifen kann. Dabei führt Ihr Browser einfach einen HTTP-GET-Request aus und das Gleiche können Sie natürlich auch mit einem Python-Programm machen. Es gibt zu diesem Zweck mehrere Python-Module. Hier verwenden wir wie in Kapitel "Datenübertragung" das elementare Socket-Modul, damit Sie sehen, wie ein GET-Request aufgebaut ist. Das Programm kann auf dem Raspberry Pi oder auf jedem anderen Computer mit Internetzugang ausgeführt werden.

Programm:[►]

# WebServer1.py

import socket 
import time
import math

host = "www.xxx.dx.am"
port = 80

for x in range(0, 101, 5):
    y = 0.5 + 0.5 * math.sin(0.1 * x) 
    print x, y
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    s.connect((host , port))
    request = "GET /insert.php?x=" + str(x) + "&y=" + str(y) + \
              " HTTP/1.1\r\nHost: " + host + "\r\n\r\n" 
    s.send(request)
    s.shutdown(1)
    s.close()
    time.sleep(5)
print "Done"
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Bemerkungen:
Nachdem Sie das Programm ausgeführt haben, können Sie wiederum das Ergebnis in Ihrem Web-Browser unter der URL http://www.xxx.dx.am/showall.php sehen.

Wenn Sie nach einigen Versuchen mit einer leeren Datenbank starten möchten, können Sie alle Datensätze entweder mit phpMyAdmin oder mit dem PHP-Script deleteall.php löschen.

Programm:

<?php
$con= mysqli_connect("host", "username",
                     "password", "database_name", "port");

$sql ="DELETE FROM temperature";
mysqli_query($con, $sql);
mysqli_close($con);
echo "All records deleted!"
?>

 

 

Datensätze über GSM einfügen (SIM800 Modem)

 

Ziel:
Schreiben Sie jede Minute das aktuelle Datum mit Uhrzeit und als simulierte y-Daten eine Zufallszahl zwischen 1 und 100 in die Temperaturtabelle. Die Daten werden von einem völlig autonomen Raspberry Pi, der über ein GSM-Modem mit Internet verbunden ist, gesendet.

Informieren Sie sich im Kapitel über GSM, wie man das SIM800-Modul einrichtet und verwendet. Im Bibliotheksmodul SIM800Modem.py sehen Sie die Funktion sendHTTPRequest(), die zum Versenden des GET-Requests verwendet wird.

Programm:[►]

# WebServer2.py

import serial
import time, sys
import datetime
from SIM800Modem import *
import random

APN = "gprs.swisscom.ch"
HOST = "www.xxx.dx.am"
PORT = 80

SERIAL_PORT = "/dev/ttyAMA0"  # Raspberry Pi 2
#SERIAL_PORT = "/dev/ttyS0"    # Raspberry Pi 3

print "Resetting modem..."
resetModem()
ser = serial.Serial(SERIAL_PORT, baudrate = 9600, timeout = 5)
if not isReady(ser):
    print "Modem not ready."
    sys.exit(0)

print "Connecting to GSM net..."
connectGSM(ser, APN)
while True:
    startTime = time.time()
    t = datetime.datetime.now()
    x = str(t)
    x = x.replace(" ", "%20") # don't use space in url
    y = random.randint(1, 100)
    print "data:", x, y
    print "Sending HTTP request..."
    reply = connectTCP(ser, HOST, PORT)
    if "CONNECT OK" not in reply:
        print "Connection failed"
        sys.exit(0)
    sendHTTPRequest(ser, HOST, "/insert.php?x=" + x + "&y=" + str(y)) 
    print "Closing. Waiting for next transfer"
    closeTCP(ser)
    isRunning = True
    while time.time() - startTime < 60:
      time.sleep(0.1)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Bemerkungen:
Da die Zeit, die es braucht, um den ersten Teil der while-Schleife durchzulaufen, nicht immer gleich lang ist, speichern wir die aktuelle Systemzeit am Anfang des Schleifenkörpers in startTime und warten am Ende der Schleife, bis 60 Sekunden abgelaufen sind. Damit ist die Periode ziemlich exakt 1 Minute.

Sie können auch hier die Tabellenwerte jederzeit mit einem Web-Browser und der URL http://www.xxx.dx.am/showall.php abrufen.

Die Datenmenge, die jede Minute übertragen wird, ist kleiner als 100 Byte. An einem Tag führt dies zu einem Datenvolumen von etwa 150 kB und in einem Monat zu etwa 4.5 MB, was in der Regel deutlich unter dem monatlichen Limit eines günstigen Mobile-Abonnements liegt. (Es gibt allerdings l auch GSM-Anbieter, die bei jedem Transfer die 100 Byte auf 1kByte aufrunden.)

 

 

Grafische Darstellung der Daten mit HTML5

 

Ziel:
Die Daten mit einem Browser vom Webserver holen und sie grafisch darstellen.

HTML5 enthält einen umfangreichen Grafiksupport. Kombiniert mit PHP und SQL können die Daten automatisch alle 5 Sekunden vom Webserver geholt und grafisch dargestellt werden.

HTML-Datei: graphik.php

<!DOCTYPE HTML>
<meta http-equiv="refresh" content="5" >

<?php
  $con= mysqli_connect("host", "username", 
     "password", "database_name", "port");
  $sql = "SELECT * FROM temperature ORDER BY id";
  $rs = mysqli_query($con, $sql);
  $totalRows_rs = mysqli_num_rows($rs);
?>

<html>
<head> 
  <script>
    function init(id) 
    {
      var cmin = 50
      var cmax = 450
      var cstep = 40
      var canvas = document.getElementById(id);
      var context = canvas.getContext('2d');
      context.font = 'bold 13pt Calibri';
	
      // Draw grid
      context.beginPath();
      context.lineWidth = 0.5;
      for (y = cmin; y <= cmax; y = y + cstep)
      {
        context.moveTo(cmin, y);
        context.lineTo(cmax, y);
      }	
      for (x = cmin; x <= cmax; x = x + cstep)
      {
        context.moveTo(x, cmin);
        context.lineTo(x, cmax);
      }	
      context.stroke();
		
      // Draw ticks
      context.font = '12pt Calibri';
      for (i = 0; i <= 10; i = i + 1)
        context.fillText(10 * i, 45 + 40 * i, 470);
      for (k = 0; k <= 10; k = k + 1)
        context.fillText(k / 10, 25, 455 - 40 * k);
      return context
    }
  </script>
</head>
<body>
  <h2>Sensor Data</h2>
  <canvas id="myCanvas" style="position:absolute; top:20px; 
           left:25px" width="500" height="510"></canvas>  
  <script>
    var context = init('myCanvas')
    context.beginPath();
    context.lineWidth = 2;
	context.strokeStyle = '#0000ff';
	<?php
    while ($row = mysqli_fetch_assoc($rs))
    {
      if ($row['x']  > 100)
        break;
	?>
    context.lineTo(<?php echo $row['x'];?> * 4 + 50, 
                450 - <?php echo $row['y'];?> * 400);
    <?php } ?>
	context.stroke();
	context.fillText('Total number of records:  ' + 
		   		<?php echo $totalRows_rs ?>, 25, 510);
  </script>
</body>
</html>
<?php
mysqli_free_result($rs);
mysqli_close($con);
?>
 

webserver5