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.
|
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:
<?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");
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); ?>
|
Datensätze vom Raspberry Pi in eine Web-Datenbank einfügen |
Ziel: 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" Bemerkungen: 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: 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) Bemerkungen: 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: 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); ?> |