Schlagwort-Archive: PHP

picam – Einfaches System für den ersten Test einer webbasierten Raspberry-Pi-Kamera (naturwatch.lite)

Zusammenfassung. Für die Anwendungsszenarien „Autarke Beobachtung von Höhlenbrütern“ und „Beobachtung des Fluglochs von Honigbienen“ (Forschungsvorhaben #biene40) sind neben dem mechanischen Aufbau (Nistkasten, wettersicherer Aufbau mit Raspberry Pi ..) auch Computerprogramme in mehreren Programmiersprachen zu programmieren. Um mit einem ersten Test sofort starten zu können, wird hier ein radikal einfaches System vorgestellt, das jeder einer halben Stunde programmieren kann. Das System nimmt ein Bild auf und lädt es auf einen Webserver. Es besteht aus einem einfachen Python-Skript auf dem Raspberry Pi, einem einfachen in PHP geschriebenem Webservice auf dem Webserver und einer minimalistischen HMTL-Seite zur Anzeige des hochgeladenen Bildes.

Anwendungsfälle (Use Case Diagramm).  Abb. 1 zeigt, was ein menschlicher Nutzer und ein als Bilderlieferant dienender Kleinrechner Raspberry Pi mit dem webbasierten Teil des Systems tun können.

Abb 1: Use Case Diagramm

Topologie (Netzwerkstruktur). Abb. 2 zeigt die Vernetzung der Geräte und der Computerprogramme. Das Gesamtsystem besteht aus:

  1. Einem Webserver. Die einzige Anforderung ist, dass der Webserver PHP unterstützt. Fast alle Providern leisten das heutzutage.
  2. Einem Raspberry Pi mit Kamera. Für den Start ist ein Raspberry Pi Zero W kostengünstig.
  3. Einem Nutzer mit Computer oder Smartphone, der die HTML-Seite aufrufen kann.
  4. Einem Python Skript „picam.py“, das auf dem Raspberry Pi läuft, ein Bild aufnimmt und über die bestehende Netzverbindung an den Webservice „picamWS.php“ überträgt.
  5. Ein PHP Skript „picamWS.php“, das auf dem Webserver läuft und ein Bild entgegennimmt und unter dem Namen „picam.jpg“ auf dem Webserver speichert.
  6. Eine HTML-Seite „picam.html“ (smartphone-geeignet), die das Bild im Browser anzeigt.

Abb. 2: Netzwerktopologie

picam.py – Bilder aufnehmen und hochladen. Das Script picam.py (netto 16 Zeilen Quelltext) kann mit einem Texteditor, z.B. nano, direkt auf dem Raspberry Pi mit der Befehlsfolge „nano picam.py“erstellt werden. Nach dem Speichern mit der Tastenkombination „ctrl+o“  wird das Script noch ausführbar gemacht mit „chmod 777 picam.py“. Das Script lässt sich dann mit „./picam.py“ aufrufen und zeigt, wenn alles richtig eingerichtet ist, die folgende Ausgabe:

pi@naturwatch02:~ $ ./picam.py
<Response [200]>
picam.jpg hochgeladen.
pi@naturwatch02:~ $

Das Script arbeitet „ohne Netz und doppelten Boden“. Der Quelltext ist in Listing 1 dargestellt und kann gleich in den Editor übernommen werden. Es ist im Script eine Programmzeile zu ändern: An der Stelle, an die URL spezifiziert wird, ist anstelle von „meinServerUndVerzeichnis“ der eigene Server und das Verzeichnis, in dem Webservice, Bild und HTML-Seite liegen sollen, anzugeben.

Zunächst werden die benötigten Bibliotheken importiert: „picamera“, um direkt Bilder aus Python aufnehmen zu können,  „sleep“ aus der Bibliothek „time“ für eine Pause für die Kamera und „requests“ für den http-Zugriff auf den Webserver.

Die spannenden Zeilen im Skript sind:

camera.capture(localpicname)

Mit dem Statement wird das Bild aufgenommen und unter localpicname gespeichert.

url = 'http://meinServerUndVerzeichnis/picamWS.php'

files = {'file': open(localpicname, 'rb')}

r = requests.post(url, files=files)

Mit den Statements werden in der Variablen „url“ der Standort des Webservice angegeben, in „files“ das Bild als Datei zum Übertragen festgelegt,  mit „requests“ der Webservice aufgerufen und das Bild hochgeladen. In der Variablen „r“ wird u.a. der Statuscode und die Antwort des Webservice gespeichert.

#!/usr/bin/python
# picam.py
# vereinfachte Version fuer naturwatch.lite
# Claus Brell 17.11.2018
import picamera
from time import sleep
import requests
# Voreinstellungen Bildgroesse:
WIDTH=320
HEIGHT=240
# Kamera initialisieren:
camera = picamera.PiCamera()
camera.resolution = (WIDTH,HEIGHT)
# Dateiname fuer Bild:
localpicname = 'picam.jpg'
# 2 Sek. Pause, damit Kamera alles einstellen kann:
sleep (2)
# Ein Bild aufnehmen:
camera.capture(localpicname)
camera.close()
# Ein Bild auf den Webspace hochladen:
# Webservice Aufruf URL festlegen:
url = 'http://meinServerUndVerzeichnis//picamWS.php'
files = {'file': open(localpicname, 'rb')}
r = requests.post(url, files=files)
# Zur Kontrolle Rueckgabe ausgeben
print(r)
print(r.text)

Listing 1: picam.py, Skript für das Aufnehmen eines Bildes und Hochladen auf den Webserver.

picamWS.php – Bild entgegennehmen und speichern. Der Webservice picamWS.php (netto 3 Zeilen Quelltext) kann mit einem einfachen Texteditor (Notepadd++ unter Windows oder Sublime Text unter MacOS oder Linux) erstellt und dann mit FTP auf den eigenen Webserver hochgeladen werden. Listing 2 zeigt das Skript, es sind keine Prüfungen oder Fehlerbehandlungen eingebaut, um das Script möglichst einfach und kurz zu halten. Die spannende Zeile ist:

if (move_uploaded_file($_FILES['file']['tmp_name'], $target_file)) {
    echo basename( $_FILES['file']['name']). " hochgeladen.";}

Es wird überprüft, ob das Kopieren des hochgeladenen Bildes in dasDateisystem des Webservers funktioniert hat, Wenn das der Fall ist, gibt es eine Bestätigung. Das Bild wird im selben Verzeichnis, in dem sich der Webservice befindet abgelegt.

<?php
// picamWS.php
// Webservice für picam.py
// nimmt Bild entgegen und speichert es auf dem Server
// naturwatch.lite
// Claus Brell 17.11.2018
// Ziel-Name, unter dem das Bild abgelegt wird:
$target_file=$mandant.'picam.jpg'; 
// Bild hochladen und uner Ziel-Name ablegen,
// wenn erfolgreicht, Meldung zurückgeben: 
if (move_uploaded_file($_FILES['file']['tmp_name'], $target_file)) {
echo basename( $_FILES['file']['name']). " hochgeladen.";
}
else echo "Fehler";
?>

Listing 2: picamWS.php – Webservice, der ein Bild entgegennimmt

picam.html – Anzeigeseite. Eine einfache HTML-Seite, die i.w. aus einem img-Tag besteht, das Bild aus dem gleichem Verzeichnis lädt und anzeigt. Die Meta-Statements sorgen dafür, dass die Anzeige auch auf einem Smartphone funktioniert.

<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="language" content="de-DE">
<meta http-equiv="Content-type" content="text/html;charset=utf-8">
<meta name="mobile-web-app-capable" content="yes">
</head>
<body>
picam Bildanzeige
<br><br>
<img src="picam.jpg">
</body>
</html>

Listing 3: picam.html – Anzeigeseite für das hochgeladene Bild

Was noch fehlt … Für eine gelungene Naturbeobachtung wäre ein Automatismus wünschenswert. Dazu kann das Python-Script einfach über CRON, z.B. jede Minute, aufgerufen werden. Dann fehlt jedoch ein ebenfalls automatisches Nachladen des Bildes in der HTML-Seite. Das ließe sich über Javascript realisieren. Möchte man kein Bild verpassen, also sollten die Bilder gespeichert werden und auch die Historie sollte einsehbar sein. Allerdings werden Webservice und Anzeigeseite dadurch sehr viel komplizierter. Wie das gehen kann, ist in einem Artikel in der Raspberry Pi Geek dargestellt (Brell 2017).

Quellen:

Brell, Claus (2017) Meisencam – Nistkästen mit der Pi-Cam ins Internet bringen. in: Raspberry Pi Geek 10 / 2017

Zeitungsartikel Rheinische Post Krefeld vom 14.03.2017:
„Auf den Spuren von Heinz Sielmann …“

Pressemitteilung der Hochschule Niederrhein vom 10.03.2017:
https://www.hs-niederrhein.de/news/news-detailseite/wirtschaftsinformatik-studierende-entwickeln-interaktiven-meisenkasten-16506/.

Tweets zum Forschungsvorhaben #biene40 – Naturschutz, Digitalisierung und Wirtschaft verbinden: https://twitter.com/hashtag/biene40

IP-Adresse (lokal) eines Raspberry Pi automatisch ermitteln

Problem:

Für z.B. die internetgestützten Meisenkästen wird der Raspberry Pi headless betrieben, das heißt: Man kommt lediglich über ssh auf den Raspberry. Dazu ist die Kenntnis der IP-Adresse erforderlich.

Lösungsansatz:

Mit einem einfachen Script ermittelt der Raspberry beim Systemstart selber seine IP-Adresse, übergibt sie an einen Webservice im Internet, der Webservice speichert die IP-Adresse ab.

Notwendige Voraussetzungen:

  1. Sie haben einen Raspberry Pi mit Internetzugang.
  2. Sie haben Zugriff auf einen Webserver, auf dem Sie PHP-Scripte speichern können.

Benötigte Scripte:

Auf dem Raspberry:

Auf dem Rasberry genügt ein einfaches Shell-Script:

#!/bin/bash
# holt IP Adresse
# ruft Webservice  auf,
# der IP-Adresse speichert
# in cron bei Neustart aufrufen
ipadr=$(hostname -I)
echo IP Adresse $ipadr
# Web Aufruf
curl "http:///service/getipWS.php?ip=$ipadr&name=Schiefbahn+Garten"
echo

Das Shell-Script rufen Sie durch einen Eintrag in CRON automatisch beim Neustart des Raspberrys auf. Die Besonderheit: Geben Sie dem Rapberry Zeit, die Verbindung zum lokalen Netzwerk aufzubauen. Das ist in dem Beispiel durch „sleep 30“ realisiert. die interessierende Zeile ist:


@reboot sleep 30; /home/pi/getip.sh >/mnt/ramdisk/getip.log

So könnte zum Beispiel Ihre Crontab aussehen:


# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command
*/30 * * * * /home/pi/wifirefresh.sh >/dev/null 2>&1
#*/10 * * * * /home/pi/naturwatchcam.py >/dev/null 2>&1
0 * * * * /home/pi/cam.py >/dev/null 2>&1
@reboot sleep 30; /home/pi/getip.sh >/mnt/ramdisk/getip.log

Auf dem Webserver:

Auf dem Webserver schreiben Sie einen Webservice (hier getipWS.php), der durch den curl-Aufruf des Raspberrys genutzt wird.


// getipWS.php
// Claus Brell, 20.05.2018
// nimmt IP entgegen, z.B. eines Raspberry Pi
// speichert IP-Adresse in getip.log
// Aufruf: getipWS?ip=192.168.1.104
// alternativ: getipWS?ip=192.168.1.104&name=mein+kleiner+Raspberry
// Rückgabe:
// ok wenn vermutlich richtiger Parameter
// fehler wenn Parameter zu lang
// ? wenn kein Parameter übergeben 
if(isset($_GET['ip'])){
    if(strlen($_GET['ip'])<16){
	  // übergebene IP in lokale Variable speichern:
	  $ip=$_GET['ip'];
	  // übergebenen Namen in lokale Variable speichern:
	  if (isset($_GET['name'])) $name=$_GET['name'];
	  else $name='unbekannt';
	  // Internetadresse, woher der Aufruf kommt: 
	  $ipremote=getenv("REMOTE_ADDR");
	  $domain=gethostbyaddr($ipremote);
	  // CSV-String zusammenstellen:
	  $ausgabe=date("ymd-His").';'.$ip.';'.$name.';'.$ipremote.';'.$domain."\r\n";
	  // CSV-String an Datei anhängen:
	  file_put_contents("getip.log",$ausgabe,FILE_APPEND);
	  echo 'ok';
    } else echo 'fehler';
} else echo '?';

Auf Ihrem Webserver finden Sie dann die Textdatei getip.log im CSV-Format, in der die lokale IP-Adresse steht. So könnte ein Beispieleintrag in getip.log aussehen:


180520-082623;192.168.0.103 ;Schiefbahn Garten;80.140.39.66;p508C2742.dip0.t-ipconnect.de