Raspberry Pi Webcam mit Twitterbot basteln

Beschreibung des Projekts

Ziel ist es, mithilfe eines Raspberry Pi und montierter RaspiCam eine Webcam zu bauen, die automatisch (z.B. alle 15 Minuten) ein Foto macht, ein Wasserzeichen und ein Textfeld hinzufügt, mit den aktuellen Wetterdaten, der Vorhersage der nächsten Tage versieht und dann auf einen selbstgehosteten Webspace via FTP hochläd. Da die Fotos nachts aufgrund der doch nur mäßigen Qualität der RasPiCam nur schwarz wären, soll der Raspi abhängig von der Geoposition Sonnenauf- und untergang berechnen und Fotos nur in diesem Zeitfenster aufnehmen. Weiterhin soll er in ebenso frei definierbaren Zeitabständen ein Foto auf dem eigenen Twitter-Account posten, also quasi als kleiner Twitterbot funktionieren.

Benötigte Hardware und Software

  • Raspberry Pi (jedes Modell ab Raspberry Pi 2 ist ausreichend – 1. Generation geht auch, es benötigt dafür aber zusätzlich einen aktiven USB-Hub wegen dem WLAN-Stick)
  • RasPi-Cam
  • WLAN-Stick (nicht bei RasPi 3, da ist es schon mit dabei), evtl. mit USB-Verlängerung (wegen dem „Geblinke“ das sonst auf den Bildern zu sehen ist)
  • Usb-Stick für die Speicherung der Daten
  • Netzteil für Micro-USB
  • Micro-SD-Karte (8GB reichen locker)
  • Twitter-Account
  • Kostenloser Entwickler-Account bei Wunderground.com
  • Eigener Webspace, auf den das Foto der RasPiCam über das FTP-Protokoll hochgeladen werden kann (z.B. bei Strato oder anderen Anbietern).
  • Ein Wasserzeichen für das Webcam-Foto im PNG-Format mit transparentem Hintergrund, „watermark.png“, das sich im Ordner /home/pi/Pictures auf dem Pi befindet.

Voraussetzungen

Diese Anleitung setzt folgendes Szenario voraus:

Die Komponenten sind zusammengesetzt, Raspbian installiert, mittels raspi-config die korrekten Land- und Zeiteinstellungen vorgenommen und das Filesystem expandiert. GUI benötigen wir nicht, wir booten in die Textkonsole und stellen den Speicher für die GUI auf das Minimum 16MB. Weiterhin sollte das WLAN-Modul aktiviert sein und der RasPi in das heimische Netz eingebunden und über eine feste IP erreichbar sein (wie das geht steht z.B. hier). Der USB-Stick wurde angesteckt, mit FAT32 formatiert und im RasPi eingebunden.

Vorarbeiten

Zunächst führen wir ein paar Standard-Vorarbeiten aus und installieren nötige Pakete:

sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get dist-upgrade -y
sudo rpi-update
sudo apt-get install python-setuptools imagemagick
sudo easy_install pip
sudo pip install twython

RAM-Disk anlegen

Um die SD-Karte des RasPi zu schonen, installieren wir eine RAM-Disk für die Logfiles und die temporären Fotos:

sudo nano /etc/fstab

Inhalt der /etc/fstab:

proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    defaults          0       2
/dev/mmcblk0p2  /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that

# RAM-Disk mit 8MB Groesse fuer die Bilder der Webcam einbinden:
tmpfs   /mnt/RAMDisk    tmpfs   nodev,nosuid,size=8M    0       0

# RAM-Disk mit 5MB Groesse für die Log-Dateien des Systems einbinden:
none    /var/log        tmpfs   size=5M,noatime 0       0

# USB-Stick 64GB mounten:
UUID="5694-7E5C" /media/usbstick/ vfat utf8,uid=pi,gid=pi,noatime 0

Der Ordner für die RAMDisk und den USB-Stick muss auch noch angelegt werden:

sudo mkdir /mnt/RAMDisk
sudo mkdir /media/usbstick
sudo mkdir /media/usbstick/Wetter

Dann RasPi neu starten um alle Änderungen wirksam werden zu lassen:

sudo shutdown -r now

Watchdog installieren

Der Hardware-Watchdog sorgt dafür, dass sich der RasPi selbstständig neu startet wenn er doch mal hängen sollte. So wird ein reibungsloser 24/7-Betrieb gewährleistet.

Kernelmodul laden und Daemon installieren:

sudo apt-get install watchdog
sudo modprobe bcm2708_wdog
echo "bcm2708_wdog" | sudo tee -a /etc/modules

Konfiguration des Watchdog anpassen:

sudo nano /etc/watchdog.conf

Nun Raute-Zeichen vor diesen beiden Zeilen entfernen:

watchdog-device        = /dev/watchdog
max-load-1             = 24

Nur für Raspbian Jessie:

sudo nano /lib/systemd/system/watchdog.service

Nun diese Einträge am Ende ergänzen:

[Install]
WantedBy=multi-user.target

 Watchdog neu starten

Für Wheezy

sudo /etc/init.d/watchdog restart

Für Jessie:

sudo systemctl enable watchdog.service
sudo systemctl start watchdog.service

Regelmäßig WLAN auf Verbindung testen

Ich habe auch bei anderen Projekten schon die Erfahrung gemacht, dass der RasPi gerne mal die Verbindung zum WLAN verliert. Möglicherweise liegt das an der schlechten Stromversorgung der USB-Ports vor allem bei den ersten Pi´s, ich weiß es aber nicht genau. Daher noch dieses Script, dass regelmäßig überprüft, ob die WLAN-Verbindung noch besteht. Ansonsten wird die Schnittstelle neu gestartet und die Verbindung automatisch wieder hergestellt.

sudo mkdir /home/Pi/Scripts/Network
sudo nano /home/pi/Scripts/Network/networkrestart.sh

Inhalt des Scripts:

###########################################################################
##                                                                       ##
##                         WLAN Reconnect Script                         ##
##                                                                       ##
## Creation:    01.02.2014                                               ##
## Last Update: 23.02.2014                                               ##
##                                                                       ##
## Copyright (c) 2014 by Georg Kainzbauer <http://www.gtkdb.de>          ##
##                                                                       ##
## This program is free software; you can redistribute it and/or modify  ##
## it under the terms of the GNU General Public License as published by  ##
## the Free Software Foundation; either version 2 of the License, or     ##
## (at your option) any later version.                                   ##
##                                                                       ##
###########################################################################
#!/bin/bash

# WLAN interface name
INTERFACE=wlan0

# Lock file
LOCKFILE=/var/tmp/wlan_connection.lock

###################################################################
# NORMALLY THERE IS NO NEED TO CHANGE ANYTHING BELOW THIS COMMENT #
###################################################################

if [ -f ${LOCKFILE} ] ; then
  /bin/kill -0 $(cat ${LOCKFILE}) >/dev/null 2>&1
  if [ $? -eq 0 ] ; then
    /bin/echo "Previous process still running."
    exit 1
  else
    /bin/echo "Deprecated lock file found. Remove lock file."
    /bin/rm -f ${LOCKFILE}
  fi
fi

/bin/echo $$ >${LOCKFILE}

/sbin/ifconfig ${INTERFACE} | grep -q "inet"
if [ $? -ne 0 ] ; then
  /bin/echo "Wireless network connection down. Attempt to reconnect."
  /sbin/ifup --force ${INTERFACE} >/dev/null 2>&1

  /sbin/ifconfig ${INTERFACE} | grep -q "inet"
  if [ $? -eq 0 ] ; then
    /bin/echo "Wireless network connection recovered."
  else
    /bin/echo "Wireless network connection still down."
  fi
else
  /bin/echo "Wireless network connection available. Nothing to do."
fi

/bin/rm -f ${LOCKFILE}

exit 0

Das Script noch in die Crontab eintragen:

sudo crontab -e

Diese beiden Zeilen am Ende der Datei ergänzen:

# WLAN-Schnittstelle alle 5 Minuten prüfen und ggfs Verbindung wieder herstellen:
0-59/5 * * * * /bin/bash /home/pi/Scripts/Network/networkrestart.sh

Nun habt Ihr eine sichere Netzwerk-Verbindung.

Wetterdaten von Wunderground.com holen

Zunächst muss hierfür ein kostenloser Entwickler-Account registriert werden, der 500 Abfragen/Tag zuläßt – für unsere Zwecke völlig ausreichend. Am Ende der Prozedur erhält man einen API-key, der im nächsten Script angegeben werden muss. Zu beachten ist, dass bei Verwendung der API ein Logo von Wunderground auf der Website platziert werden muss.

Zunächst mal Ordner anlegen um etwas Ordnung in die Sache zu bringen:

sudo mkdir /home/pi/Scripts
sudo mkdir /home/pi/Scripts/WebCam
sudo mkdir /home/pi/Scripts/Wetter

Dann legen wir die Datei „get_weather.py“ im Verzeichnis „Wetter“ an:

sudo nano /home/pi/Scripts/Wetter/get_weather.py

Der Inhalt der Datei ist wie folgt:

#!/usr/bin/python3 
# -*- coding: utf-8 -*-

# Module laden
import sys;
reload (sys);
sys.setdefaultencoding("utf8")
from time import *
from shutil import copyfile
import requests,urllib2,json,os.path,io

# Variablen anlegen:
key = "**************" #API-Key bei Wunderground
ort = "Berchtesgaden" #Ort der Abfrage
land = "Germany" #Land der Abfrage
wetterdatei = "/media/usbstick/Wetter/wetterlog.cat" #Pfad zur Datendatei
backupordner = "/media/usbstick/Wetter/Backup_BGD" #Ordner für Backup der Datendatei
vorhersagedatei = "/media/usbstick/Wetter/Vorhersage_bgd.txt" #Datei für die Wettervorhersage der nächsten 3 Tage

# Ab hier muss nichts mehr verändert werden:
liste = [0,0,0,0,0,0,0,0,0,0]   #Array für die aktuellen Wetterdaten
degreeChar = u'\N{DEGREE SIGN}' #Gradzeichen erzeugen
fcast = []
# Aktuelles Datum und Uhrzeit
lt = localtime()
datum = strftime("%d.%m.%Y", lt)
zeit = strftime("%H:%M", lt)
# Pfad zur Backup-Datei erstellen:
timestamp = strftime("%Y_%m_%d", lt)

# Hier startet das Hauptprogramm:
print("Hole Daten von Wunderground...")

# Wetterdaten aktuell bei Wunderground abholen
url = 'http://api.wunderground.com/api/' + key + '/geolookup/conditions/lang:DL/q/' + land + '/' + ort + '.json'
f = urllib2.urlopen(url)
json_string = f.read()
parsed_json = json.loads(json_string)
city = parsed_json['location']['city']
state = parsed_json['location']['state']
weather = parsed_json['current_observation']['weather']
temperature_string = parsed_json['current_observation']['temperature_string']
feelslike_string = parsed_json['current_observation']['feelslike_string']

# Aktuelle Bedingungen ausgeben:
print 'Das Wetter in ' + city + ', ' + state + ': ' + weather.lower() + \
      '. Die Temperatur ist ' + temperature_string + ' aber es fuehlt sich an wie ' + \
      feelslike_string + '.'

# Aktuellen Ort holen:
location = parsed_json['location']['city']

# Aktuelle Temperatur in Grad holen:
temp_c = parsed_json['current_observation']['temp_c']

# Aktuelle Luftfeuchtigkeit in Prozent holen
hum = parsed_json['current_observation']['relative_humidity']

f.close()

# Vorhersage holen:
url = 'http://api.wunderground.com/api/' + key + '/forecast/astronomy/lang:DL/q/' + land + '/' + ort + '.json'
r = requests.get(url)
data=r.json() # data contains the parsed JSON string
r.close()
i=0
for day in data['forecast']['simpleforecast']['forecastday']:
   x=day['date']['weekday_short'] + ":"
   y=day['conditions']
   z = day['high']['celsius'] + degreeChar+"C/" + day['low']['celsius'] + degreeChar+"C"
   fcast.append(x + " " + y + " " + z)
   if i==0:
       # Maximale Tagestemperatur holen:
       temp_max=day['high']['celsius']
       # Minimale Tagestemperatur holen:
       temp_min=day['low']['celsius']
       # Wettertext holen:
       condition=day['conditions']
       #condition=condition.encode('ascii', "replace") # Umlaute gegen Fragezeichen austauschen (Quick and Dirty)
       condition=condition.replace(" ", "_") # Leerzeichen gegen _ austauschen, sonst gibts Probleme in der Bash
       # Sonnenaufgang holen:
       sunrise_hour = data['sun_phase']['sunrise']['hour']
       sunrise_minute = data['sun_phase']['sunrise']['minute']
       sunrise = str(sunrise_hour + ":" + sunrise_minute)
       # Sonnenuntergang holen:
       sundown_hour = data['sun_phase']['sunset']['hour']
       sundown_minute = data['sun_phase']['sunset']['minute']
       sundown = str(sundown_hour + ":" + sundown_minute)
   i=i+1

# Wetterdaten in Liste schreiben:
liste[0] = datum        #Datum
liste[1] = zeit         #Zeit
liste[2] = location     #Ort
liste[3] = temp_c       #Aktuelle Temperatur
liste[4] = hum          #Luftfeuchtigkeit
liste[5] = temp_max     #Tagesmaximaltemperatur
liste[6] = temp_min     #Tagesminimaltemperatur
liste[7] = sunrise      #Sonnenaufgang
liste[8] = sundown      #Sonnenuntergang
liste[9] = condition        #Wetterbedingungen.

# Zeile für Wetterdatei generieren:
line = (str(liste[0])+";"+str(liste[1])+";"+str(liste[2])+";"+str(liste[3])+ \
       ";"+str(liste[4])+";"+str(liste[5])+";"+str(liste[6])+";"+str(liste[7])+ \
       ";"+str(liste[8])+";"+str(liste[9]))

# Falls Wetterdatei noch nicht existiert, diese anlegen:
if not os.path.exists(wetterdatei):
        fout=open(wetterdatei,"w")
    fout.close()
    print("Habe keine Wetterdatei im Verzeichnis gefunden - neue Datei angelegt")

# Backup Wetterdatei anlegen:
backupdatei=str(backupordner + '/' + timestamp + '_backup.cat')
if not os.path.exists(backupdatei): #Nur einmal am Tag Backup anlegen, falls Datei noch nicht existiert
    copyfile(wetterdatei,backupdatei)
    print("Backup erstellt in " + backupdatei)
else:
    print("Backup wurde heute schon einmal erstellt - Skipped")

# Zeile an Wetterdatei anhängen:
fout=open(wetterdatei,"a")
fout.writelines(line + '\n')
fout.close()
print(wetterdatei+" wurde ergänzt.")
print("Die neue Zeile sieht so aus:\n" + line)

# Vorhersage der nächsten Tage in zweite Datei schreiben:
fout=open(vorhersagedatei,"w")          #Alte Datei wird überschrieben...
for day in fcast:
    fout.write("%s\n" % day)            #Vorhersage aus Liste in Datei schreiben
fout.close()                            #Datei schließen
print("Wettervorhersage der nächsten 3 Tage in "+vorhersagedatei+" geschrieben.")

# Programm wird beendet:
print("Programm vollständig abgearbeitet.")

Wie immer wird das Script ausführbar gemacht:

sudo chmod +x /home/pi/Scripts/Wetter/get_weather.py

Letztlich holt das Script die Wettervorhersage in Form einer JSON-Datei. Diese wird ausgelesen und die Daten in zwei Dateien geschrieben:

  • eine „Wetterdatei“, die die aktuellen Bedingungen im CSV-Format enthält. Die aktuellen Bedingungen werden jeweils als neue Zeile an die Datei angehängt. So sind in der Zukunft statistische Auswertungen und grafische Darstellungen über einen längeren Zeitraum möglich. Von dieser Datei wird einmal am Tag automatisch ein Backup angelegt.
  • Eine „Vorhersagedatei“, die jeweils die bereits bestehende überschreibt und die Vorhersage der nächsten 3 Tage enthält.

Beide Dateien werden später vom Script, welches die Fotos schießt, ausgelesen und die Daten verwendet.

Bash-Dateien für die Fotos

Nun erstellen wir die Scripts für die RasPiCam um endlich mal Fotos schießen zu können.

Script für die Fotoaufnahme (Webcam)

Das folgende Script arbeitet so:

  • Wetterdaten aus beiden oben angelegten Dateien auslesen
  • Foto in geringerer Größe für die Webcam aufnehmen
  • Schlusszeile ergänzen
  • Wetterdaten aus den beiden o.g. Dateien ergänzen
  • Wasserzeichen einfügen
  • Upload auf den Webspace via FTP
  • Foto wieder von der RAM-Disk löschen
sudo nano /home/pi/Scripts/WebCam/takeapictureWebcam.sh

Hier der Inhalt der Datei:

#!/bin/bash

############# WEBCAM-FOTO AUFNEHMEN, MIT WETTERDATEN VERSEHEN UND HOCHLADEN #####################

# Variablen:
wetterdatei="/media/usbstick/Wetter/wetterlog.cat" #Pfad zur Wetterdatei
vorhersagedatei="/media/usbstick/Wetter/vorhersage_bgd.txt" #Pfad zur Vorhersagedatei
conditions=""
declare -a liste #Array für die Wetterbedingungen
aktuelle_uhrzeit=`date +%H:%M`

############## Wetterdatei (CSV) auslesen ##########################
# Letzte Zeile der Wetterdatei auslesen:
lastline=$(wc -l $wetterdatei | cut -d " " -f 1)  #Zeilenanzahl der Datei
export conditions=$(cat $wetterdatei | head -n$lastline | tail -n1)  #Letzte Zeile auslesen

# Zeile zerlegen an den Semikolons und Array füllen:
text=$(echo $conditions | tr ";" "\n")
counter=0
for value in $text
do
    liste[counter]=$value
    counter=$(( $counter + 1 ))
done

# Wetterdaten aus Array in Variablen schreiben:
datum=${liste[0]}
zeit=${liste[1]}
ort=${liste[2]}
temp_c=${liste[3]}
hum=${liste[4]}
temp_max=${liste[5]}
temp_min=${liste[6]}
sunrise=${liste[7]}
sundown=${liste[8]}
cond=${liste[9]}
cond=$(echo $cond | tr '_' ' ') # _ wieder gegen Leerzeichen bei den Aktuellen Bedingungen austauschen

############## Vorhersagedatei (TXT) auslesen ##########################
# Vorhersagedaten in Variablen schreiben:
export vorhersage_tag_0=$(cat $vorhersagedatei | head -n1 | tail -n1)  #Erste Zeile auslesen
export vorhersage_tag_1=$(cat $vorhersagedatei | head -n2 | tail -n1)  #Zweite Zeile auslesen
export vorhersage_tag_2=$(cat $vorhersagedatei | head -n3 | tail -n1)  #Dritte Zeile auslesen
export vorhersage_tag_3=$(cat $vorhersagedatei | head -n4 | tail -n1)  #Vierte Zeile auslesen

############## Texte zusammenbauen ####################################
# Untertitel für die Webcam zusammenbauen:
untertitel1=$ort", "$datum", "$aktuelle_uhrzeit" Uhr, Temperatur: "$temp_c"°C, Luftfeuchtigkeit: "$hum", "$cond". Temp. max: "$temp_max"°C, Temp. min.: "$temp_min"°C"
untertitel2="Sonnenaufgang: "$sunrise" Uhr, Sonnenuntergang: "$sundown" Uhr. Die Daten werden freundlichweise von Wunderground.com zur Verfügung gestellt. Daten von "$zeit" Uhr."

############## Foto machen und alles zusammensetzen ###################
#Kamerabild für Webcam aufnehmen und auf RAM-Disk speichern:
raspistill -w 1024 -h 768 -q 70 -t 3000 -sh 10 -ex auto -awb auto -o /mnt/RAMDisk/foto.jpg

#aufgenommenes Webcam-Bild mit Textstring versehen
convert /mnt/RAMDisk/foto.jpg \
-geometry 1024x768 \
-quality 80 \
-gravity North \
-background black \
-extent 1024x802 \
-gravity SouthEast \
-fill white \
-pointsize 16 \
-draw "text 0,15 '$untertitel1'" \
-pointsize 12 \
-draw "text 0,0 '$untertitel2'" \
-gravity NorthWest \
-pointsize 16 \
-draw "text 10,15 'Vorhersage:'" \
-pointsize 14 \
-draw "text 10,34 '$vorhersage_tag_1'" \
-draw "text 10,50 '$vorhersage_tag_2'" \
-draw "text 10,66 '$vorhersage_tag_3'" \
/mnt/RAMDisk/foto.jpg

#aufgenommenes Webcam-Bild mit Watermark versehen
composite -dissolve 80% -quality 100 -geometry +800+20 /home/pi/Pictures/Nordlandcamper_Logo_klein.png /mnt/RAMDisk/foto.jpg /mnt/RAMDisk/webcam.jpg

# Hilfsbild von der RAM-Disk löschen
rm /mnt/RAMDisk/foto.jpg

#Kamerabild für Webcam via FTP hochladen
HOST='***********'
USER='************'
PASSWD='*************'

cd /mnt/RAMDisk
ftp -n -v $HOST << EOT
ascii
user $USER $PASSWD
cd /WordPress_01/wp-content/uploads/webcam  # In den Ordner auf dem FTP-Server wechseln
prompt
mput *.jpg
bye
EOT

#Bild wieder von der RAMDisk löschen
rm /mnt/RAMDisk/webcam.jpg

Nun noch die Datei ausführbar machen:

sudo chmod +x /home/pi/Scripts/WebCam/takeapictureWebcam.sh

Script für die Fotoaufnahme auf den USB-Stick (TimeShift-Aufnahme)

Die TimeShift-Aufnahme soll in guter Qualität erfolgen. Dabei soll der Zeitintervall kürzer sein, als bei der Aufnahme für die Webcam. Zur Durchführung der Aufnahme dienst folgendes Script:

Zunächst legen wir einen passenden Ordner auf dem USB-Stick an:

mkdir /media/usbstick/TimeShift
sudo nano /home/pi/Scripts/WebCam/takeapictureUSBStick.sh
#!/bin/bash

############## TIME-SHIFT-FOTO AUFNEHMEN UND AUF USB-STICK SPEICHERN ####################

#Kamerabild in guter Qualität für Zeitrafferaufnahme aufnehmen und auf RAM-Disk speichern:
timestamp=$(date +%Y-%m-%d-%H-%M)
filename=/mnt/RAMDisk/$timestamp.jpg
raspistill -w 2592 -h 1944 -q 75 -t 3000 -sh 10 -ex auto -awb auto -o $filename

#Kamerabild für TimeShift-Berechnung auf USB-Stick speichern:
sudo cp $filename /media/usbstick/TimeShift/$timestamp.jpg

#Bild wieder von der RAMDisk löschen
rm $filename

Und wieder ausführbar machen:

sudo chmod +x /home/pi/Scripts/WebCam/takeapictureUSBStick.sh

Script für die Fotoaufnahme und Upload auf den FTP-Server (z.B. Synology-Diskstation)

Das folgende Script erledigt die Fotoaufnahme und den Upload eines qualitativ guten Fotos auf einen FTP-Server:

sudo nano /home/pi/Scripts/WebCam/takeapictureFTP.sh
#!/bin/bash

############## TIME-SHIFT-FOTO AUFNEHMEN UND AUF FTP-SERVER HOCHLADEN ####################

#Kamerabild in guter Qualität für Zeitrafferaufnahme aufnehmen und auf RAM-Disk speichern:
timestamp=$(date +%Y-%m-%d-%H-%M)
filename=/mnt/RAMDisk/$timestamp.jpg
raspistill -w 2592 -h 1944 -q 75 -t 3000 -sh 10 -ex auto -awb auto -o $filename

#Kamerabild für Zeitrafferaufnahme via FTP auf Synology DS214play hochladen
HOST='IP der Diskstation'
USER='*************'
PASSWD='*************'

cd /mnt/RAMDisk
ftp -n -v $HOST 59122 << EOT
ascii
user $USER $PASSWD
cd /FTP/WebCam/TimeShift        # In den Ordner auf dem FTP-Server wechseln
prompt
mput *.jpg
bye
EOT

#Bild wieder von der RAMDisk löschen
rm $filename

Und wieder ausführbar machen:

sudo chmod +x /home/pi/Scripts/WebCam/takeapictureFTP.sh

Zentrales Script für die Steuerung der Fotoaufnahme

Was uns nun noch fehlt, ist das zentrale Script für die Steuerung der Fotoaufnahme aus welchem heraus alle anderen Scripts aufgerufen werden. Für die Berechnung der Zeit des Sonnenaufgang und -untergangs habe ich ein tolles Script gefunden (herzlichen Dank an dieser Stelle an den Autor für die genialen Berechnungen, die ich nicht ansatzweise verstehe…), dass ich für meine Zwecke entsprechend abgeändert habe. Letztlich werden die aktuelle Tageszeit, Sonnenauf- und -untergang in einen Sekundenwert umgerechnet. So ist eine einfache Vergleichsabfrage möglich, ob ein Foto gemacht werden soll, oder eben nicht.

sudo nano /home/pi/Scripts/WebCam/talktowebcam.sh

Mit dem Script wird abhängig von der Geoposition der Webcam Sonnenauf- und Untergang berechnet. Angepaßt werden muss lediglich die Geoposition der Webcam, die über Google einfach erfahren werden kann. Durch die Veränderung der drei Arrays „time_webcam“, „time_usbstick“ und „time_ftp“ kann die jeweilige Aufnahmezeit angepaßt werden.

#!/bin/bash
#########################################################################################
# Dieses Script berechnet anhand der Geo-Position den Sonnenauf- und Sonnenuntergang
# Dann entscheidet das Script, ob ein Foto gemacht werden soll, oder nicht
# (Nur zwischen Sonnenauf- und Sonnenuntergang ggfs. mit Offset)
#
# Folgende Fotoarten werden unterstützt:
# -Foto auf Webspace laden (Webcam)
# -Foto auf USB-Stick laden (höhere Auflösung)
# -Foto auf FTP-Server laden (höhere Auflösung)
# -Foto twittern (Sonnenauf- und Untergang)
#
#########################################################################################

##################################################
# Definition der Variablen
##################################################
# Unsere Position
posLaenge="13.0"
posBreite="46.3"
# Zeiten für die Fotoaufnahme definieren (Minuten) über ein Array
time_webcam=("0" "10" "20" "30" "40" "50") #Alle 10 Minuten ein Foto für die Webcam
time_usbstick=("0" "5" "10" "15" "20" "25" "30" "35" "40" "45" "50" "55") #Alle 5 Minuten ein Foto für den USB-Stick
time_ftp=()
# Offset für Fotoaufnahme vor Sonnenaufgang (in Sekunden):
offset_sonnenaufgang=3600
# Offset für Fotoaufnahme nach Sonnenuntergang (in Sekunden):
offset_sonnenuntergang=900

##################################################
# Notwendige Vorberechnungen
##################################################
zoneinfo=$(date +%z) # Zeitzone
T=`date +%j` # Tag im Jahr
pi="3.14159265358979323844" # pi=`echo "4*a(1)" | bc -l`
rad=$(echo "${pi}/180" | bc -l)
h=$(echo "-(5/6)*(${rad})" | bc -l) # Höhe des Sonnenmittelpunkts bei Aufgang: Radius+Refraktion
BreiteRAD=$(echo "${posBreite}*${rad}" | bc -l)

# Welcher Tag ist heute?
echo "Heute ist $(date +%d.%m.%y), der $(date +%j). Tag im Jahr"

echo -n "Wir nutzen die Zeitzone $(date +%Z), dies entspricht $(date +%z) und damit "
echo "${zoneinfo:0:3}"

sonnendekl=`echo "0.409526325277017*s(0.0169060504029192*(${T}-80.0856919827619))" | bc -l`
sonnendeklDEG=$(echo "${sonnendekl} / ${rad}" | bc -l)

arccosint=$(echo "(s(${h})-s(${BreiteRAD})*s(${sonnendekl}))/(c(${BreiteRAD})*c(${sonnendekl}))" | bc -l)
arccosintsign=${arccosint:0:1}
if [ ${arccosintsign} == "-" ]; then
 usesign="+"
else
 usesign="-"
fi
arc2cosint=$(echo "(${arccosint}) * (${arccosint})" | bc -l)
acoszeit=$(echo "${pi}/2 ${usesign} a(sqrt(${arc2cosint} / (1 - (${arc2cosint}) ) ) ) " | bc -l)

zeitdiff=$(echo "12*${acoszeit}/${pi}" | bc -l) # KORREKT!

zeitgleich=$(echo "-0.170869921174742*s(0.0336997028793971 * ${T} + 0.465419984181394) - 0.129890681040717*s(0.0178674832556871*${T} - 0.167936777524864)" | bc -l)
aufgang=$(echo "12-(${zeitdiff})-(${zeitgleich})-(${posLaenge}/15)${zoneinfo:0:3}" | bc -l)
untergang=$(echo "12+(${zeitdiff})-(${zeitgleich})-(${posLaenge}/15)${zoneinfo:0:3}" | bc -l)

if [ ${aufgang:1:1} == "." ]; then
 # Ist ein einstelliges Ergebnis der Form x.xxxx, wir brauchen noch eine 0 vorne
 aufgang=$(echo 0${aufgang})
fi
# Fuer unsere Breitengrade ueberfluessig, nur der Vollstaendigkeit halber:
#if [ ${untergang:1:1} == "." ]; then
# Ist ein einstelliges Ergebnis der Form x.xxxx, wir brauchen noch eine 0 vorne
# untergang=$(echo 0${untergang})
#fi

# Umrechnung in Stunden (trivial) und Minuten (runden!)
AufgangMinute=$(echo "(${aufgang} - ${aufgang:0:2}) * 60" | bc | xargs printf "%02.0f\n")
if [ ${AufgangMinute} == "60" ]; then
 AufgangMinute="00"
 AufgangStunde=$(echo "${aufgang:0:2} + 1" | bc | xargs printf "%02.0f")
else
 AufgangStunde=${aufgang:0:2}
fi
echo "Aufgang (hh:mm): ${AufgangStunde}:${AufgangMinute}" # Immer ein zweistelliges Ergebnis


UntergangMinute=$(echo "(${untergang} - ${untergang:0:2}) * 60" | bc | xargs printf "%02.0f\n")
if [ ${UntergangMinute} == "60" ]; then
 UntergangMinute="00"
 UntergangStunde=$(echo "${untergang:0:2} + 1" | bc | xargs printf "%02.0f")
else
 UntergangStunde=${untergang:0:2}
fi
echo "Untergang (hh:mm): ${UntergangStunde}:${UntergangMinute}" # Immer ein zweistelliges Ergebnis

################################################
# Bestimmung der aktuellen Zeitwerte:
################################################
aktuelle_stunde=`date +%-H`
aktuelle_minute=`date +%-M`

# Aktuelle Tageszeit in Sekunden umrechnen:
aktuelle_tagessekunden=$(((($aktuelle_stunde * 60)+$aktuelle_minute)*60))

# Sonnenaufgangszeit in Sekunden umrechnen:
sun_up_sekunden=$((((($AufgangStunde * 60)+$AufgangMinute)*60)-offset_sonnenaufgang)) #Aufnahme beginnt mit Offset vor dem Sonnenaufgang

# Sonnenuntergangszeit in Sekunden umrechnen:
sun_down_sekunden=$((((($UntergangStunde * 60)+$UntergangMinute)*60)+offset_sonnenuntergang)) #Aufnahme endet mit Offset nach Sonnenuntergang

################################################
# Fotos knipsen und ggfs. hochladen:
################################################
if [ $aktuelle_tagessekunden -lt $sun_up_sekunden ]
 then
 # Es ist zu früh:
 echo "Es ist zu früh"
 else
 if [ $aktuelle_tagessekunden -gt $sun_down_sekunden ]
 then
 #Es ist zu spät:
 echo "Es ist zu spät"
 else
 # Die aktuelle Uhrzeit ist im Intervall, wo es hell genug ist, ein Foto zu machen
 # Steht die aktuelle Minute im Array für die Webcam-Zeiten?
 for i in "${time_webcam[@]}"
 do
 if [ $aktuelle_minute == $i ]
 then
 # Ja, Foto machen:
 echo "Mache Foto für Webcam-Server..."
 /bin/bash /home/pi/Scripts/WebCam/takeapictureWebcam.sh # Foto für die Webcam machen und hochladen
 fi
 done
 # Steht die aktuelle Minute im Array für die USB-Stick-Zeiten?
 for i in "${time_usbstick[@]}"
 do
 if [ $aktuelle_minute == $i ]
 then
 # Ja, Foto machen:
 echo "Schreibe Foto auf USB-Stick..."
 /bin/bash /home/pi/Scripts/WebCam/takeapictureUSBStick.sh # Foto machen und auf den USB-Stick speichern
 fi
 done
 # Steht die aktuelle Minute im Array für die FTP-Aufnahme-Zeiten?
 for i in "${time_ftp[@]}"
 do
 if [ $aktuelle_minute == $i ]
 then
 # Ja, Foto machen:
 echo "Schreibe Foto auf FTP-Server..."
 /bin/bash /home/pi/Scripts/WebCam/takeapictureFTP.sh # Foto für den FTP-Server machen und hochladen
 fi
 done
 # Am Sonnenaufgang noch ein Foto für Twitter machen:
 if [ $aktuelle_stunde -eq $AufgangStunde ]
 then
 if [ $aktuelle_minute -eq $AufgangMinute ]
 then
 # Es ist Sonnenaufgang -> Foto für Twitter machen
 echo "Es ist Sonnenaufgang, twittere Foto..."
 /bin/bash /home/pi/Scripts/WebCam/takeapicture_for_tweet.sh
 fi
 else
 echo "Es wird kein Sonnenaufgangsfoto getwittert, die Zeit stimmt nicht..."
 fi 
 # Am Sonnenuntergang noch ein Foto für Twitter machen:
 if [ $aktuelle_stunde -eq $UntergangStunde ]
 then
 if [ $aktuelle_minute -eq $UntergangMinute ]
 then
 # Es ist Sonnenuntergang -> Foto für Twitter machen
 echo "Es ist Sonnenuntergang, twittere Foto..."
 /bin/bash /home/pi/Scripts/WebCam/takeapicture_for_tweet.sh
 fi
 else
 echo "Es wird kein Sonnenuntergangsfoto getwittert, die Zeit stimmt nicht..."
 fi

 fi
fi

Nun noch die Datei ausführbar machen:

sudo chmod +x /home/pi/Scripts/WebCam/talktowebcam.sh

Crontab anpassen

Um das Scripts z.B. alle 15 Minuten auszuführen, muss wieder ein Eintrag in der Crontab erstellt werden:

sudo crontab -e

Unten ergänzen:

# Jede Minute zwischen 3 und 22 Uhr prüfen, ob Fotos gemacht werden sollen:
*/1 3-22 * * * /bin/bash /home/pi/Scripts/WebCam/talktowebcam.sh

Sicherheitshalber habe ich noch ein Zeitfenster in der Crontab eingetragen, was aber eigentlich nicht nötig wäre.

Webcam-Foto twittern

Nun sind wir schon fast am Ziel. Was nun noch fehlt, ist ein Twitterbot, der z.B. einmal am Tag ein Foto der Webcam auf dem eigenen Twitter-Account postet. Das ist gar nicht so schwer und funktioniert so:

Das Script

Zunächst das Script, welches ein Foto für Twitter schießt und aufbereitet (wie zuvor):

sudo nano /home/pi/Scripts/WebCam/takeapicture_for_tweet.sh

Inhalt des Scripts:

#!/bin/bash

############# WEBCAM-FOTO FR TWEET AUFNEHMEN #####################

# Variablen:
wetterdatei="/media/usbstick/Wetter/wetterlog.cat" #Pfad zur Wetterdatei
conditions=""
declare -a liste #Array für die Wetterbedingungen
aktuelle_uhrzeit=`date +%H:%M`

# Letzte Zeile der Datei auslesen:
lastline=$(wc -l $wetterdatei | cut -d " " -f 1)  #Zeilenanzahl der Datei
export conditions=$(cat $wetterdatei | head -n$lastline | tail -n1)  #Letzte Zeile auslesen

# Zeile zerlegen an den Semikolons und Array füllen:
text=$(echo $conditions | tr ";" "\n")
counter=0
for value in $text
do
    liste[counter]=$value
    counter=$(( $counter + 1 ))
done

# Wetterdaten aus Array in Variablen schreiben:
datum=${liste[0]}
zeit=${liste[1]}
ort=${liste[2]}
temp_c=${liste[3]}
hum=${liste[4]}
temp_max=${liste[5]}
temp_min=${liste[6]}
sunrise=${liste[7]}
sundown=${liste[8]}
cond=${liste[9]}
cond=$(echo $cond | tr '_' ' ') # _ wieder gegen Leerzeichen bei den Aktuellen Bedingungen austauschen

# Untertitel für die Webcam zusammenbauen:
untertitel1=$ort", "$datum", "$aktuelle_uhrzeit" Uhr, Temperatur: "$temp_c"°C, Luftfeuchtigkeit: "$hum", "$cond". Temp. max: "$temp_max"°C, Temp. min.: "$temp_min"°C"
untertitel2="Sonnenaufgang: "$sunrise" Uhr, Sonnenuntergang: "$sundown" Uhr. Die Daten werden freundlichweise von Wunderground.com zur Verfügung gestellt. Daten von "$zeit" Uhr."

#Kamerabild für Tweet aufnehmen und auf RAM-Disk speichern:
raspistill -w 1024 -h 768 -q 70 -t 3000 -sh 10 -ex auto -awb auto -o /mnt/RAMDisk/foto_tweet.jpg

#aufgenommenes Webcam-Bild mit Textstring versehen
convert /mnt/RAMDisk/foto_tweet.jpg \
-geometry 1024x768 \
-quality 80 \
-gravity North \
-background black \
-extent 1024x802 \
-gravity SouthEast \
-fill white \
-pointsize 16 \
-draw "text 0,15 '$untertitel1'" \
-pointsize 12 \
-draw "text 0,0 '$untertitel2'" \
/mnt/RAMDisk/foto_tweet.jpg

#aufgenommenes Webcam-Bild mit Watermark versehen
composite -dissolve 80% -quality 100 -geometry +800+20 /home/pi/Pictures/Nordlandcamper_Logo_klein.png /mnt/RAMDisk/foto_tweet.jpg /mnt/RAMDisk/tweet.jpg

#Kamerabild twittern
python /home/pi/Scripts/WebCam/tweety.py

#Bilder wieder von der RAMDisk löschen
rm /mnt/RAMDisk/tweet.jpg
rm /mnt/RAMDisk/foto_tweet.jpg

Nun wieder die Datei ausführbar machen:

sudo chmod +x /home/pi/Scripts/WebCam/takeapicture_for_tweet.sh

Anwendung bei Twitter regististrieren

Einen eigenen Twitter.Account vorausgesetzt, registriert man hier seine geplante Anwendung. Das Ergebnis sind dann 4 Codes, die in dieses Script ergänzt werden:

sudo nano /home/pi/Scripts/WebCam/tweety.py

Inhalt des Scripts:

#!/usr/bin/python

import sys
from twython import Twython

CONSUMER_KEY = '********'
CONSUMER_SECRET = '************'
ACCESS_KEY = '************'
ACCESS_SECRET = '************'

twitter = Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)

photo = open('/mnt/RAMDisk/tweet.jpg','rb')
twitter.update_status_with_media(media=photo, status='#Webcam #Raspberry')

Auch dieses Script wieder ausführbar machen:

sudo chmod +x /home/pi/Scripts/WebCam/tweety.py

Das Script wird automatisch über da zentrale Script in der Crontab aufgerufen (ist dort schon entsprechend eingetragen). Es wird (falls kein Offset eingetragen wird) passend zum Sonnenuntergang und Sonnenaufgang jeweils ein Foto geschossen und gepostet. Das Ergebnis des Ganzen sieht auf Twitter dann so aus.

Die Crontab

Der Übersicht halber hier nochmal ein Abdruck der gesamten Crontab:

# WLAN-Schnittstelle alle 5 Minuten prüfen und ggfs Verbindung wieder herstellen:
0-59/5 * * * * /bin/bash /home/pi/Scripts/Network/networkrestart.sh

# Jede Minute zwischen 3 und 23 Uhr prüfen, ob ein Foto gemacht werden soll:
*/1 3-23 * * * /bin/bash /home/pi/Scripts/WebCam/talktowebcam.sh

# Jede Stunde einmal die Wetterdaten von Wunderground holen und in Log-Datei schreiben:
00 */1 * * * /usr/bin/python2 /home/pi/Scripts/Wetter/get_weather.py

# Falls es zu unklaren Fehlern während der Ausführung von Scripten kommt,
# kann mit diesem Befehl (hinter das Script platziert) die Ausgabe in eine Datei umgeleitet werden:
# > /tmp/listener.log 2>&1

Samba-Server installieren

Damit wir nun bequem vom Computer aus auf den angeschlossenen USB-Stick Zugriff haben, installieren wir noch einen Samba-Server auf dem RasPi:

sudo apt-get install samba samba-common-bin

Nun erstellt man ein Passwort für den User „pi“. Hiermit kann man sich dann vom PC/Mac aus einloggen:

sudo smbpasswd -a pi

Nun evtl. noch die Berechtigungen für den USB-Stick setzen (User pi wird als Besitzer eingetragen):

sudo chown -R pi:pi /media/usbstick

An die Konfigurationsdatei vom Samba-Server nun noch ein paar Zeilen Code anhängen:

sudo nano /etc/samba/smb.conf
[raspicamUSBStick]
path = /media/usbstick
writeable = yes
guest ok  = no

In einem letzten Schritt den Samba-Server neu starten:

sudo /etc/init.d/samba restart

Nun kann man auf dem PC/Mac eine neue Freigabe „smb://IP des Pi“ erstellen, gibt die o.g. Zugangsdaten ein und hat ab sofort bequemen Zugriff auf die Fotos auf dem USB-Stick.

Die Krönung des Ganzen: Grafische Darstellung der Wetterdaten

Wer sich bis hierhin tapfer durchgearbeitet hat, möchte vielleicht noch die Wetterdaten, welche wir in die beiden log-Dateien geschrieben haben, grafisch auswerten und z.B. auf seinem Webspace präsentieren. Hierzu bietet sich GnuPlot für den RasPi an. Dem Plot-Programm kann man ein Script übergeben, welches dann zeilenweise abgearbeitet wird und das Aussehen des Plots sowie die Output-Datei bestimmt.

Aussehen wird das Ganze dann z.B. so:

4-Wochen Übersicht

Zunächst installieren wir GnuPlot:

sudo apt-get install gnuplot gnuplot-x11

Dann legen wir auf dem RasPi und dem USB-Stick weitere Ordner an:

mkdir /home/pi/Scripts/GnuPlot
mkdir /media/usbstick/GnuPlot

Anlegen des zentralen Scripts für die Generierung der Plots:

nano /home/pi/Scripts/GnuPlot/generate_gnuplots.sh
#!/bin/bash
##############################################################################
# Script zum Erzeugen und Hochladen der Grafikplots für die Wetterdarstellung
# Hierzu wird Gnuplot verwendet und die Config-Datei jeweils entsprechend
# abgeändert. Weiterhin wird dann auf jeden erzeugten Plot ein eigenes
# Wasserzeichen und ein Wasserzeichen von Wunderground platziert.
# Zuletzt erfolgt ein FTP-Upload auf den Webspace
#
# Script by Matthias Pfeifer
# darf jederzeit verändert und nicht-kommerziell verwendet werden
##############################################################################

# Pfad zu den Wasserzeichen:
wasserzeichen_1="/media/usbstick/GnuPlot/Wasserzeichen/Nordlandcamper_Logo_klein.png"
wasserzeichen_2="/media/usbstick/GnuPlot/Wasserzeichen/wundergroundLogo_4c_horz.png"

# Aktuelles Datum generieren:
datum_heute=$(date +%d.%m.%Y)
datum_letzter_monat=$(date -d "-4 weeks" +%d.%m.%Y)
datum_letzte_sechs_monate=$(date -d "-6 months" +%d.%m.%Y)
datum_letztes_jahr=$(date -d "-1 year" +%d.%m.%Y)

################### Grafikplots für Asele erzeugen #######################
# Es muss jeweils das Datum und der Dateiname in der Config angepaßt werden
# bevor der Plot durchgeführt wird
echo "Starte Berechnung der Plots für Asele..."
# Configdatei ändern:
configdatei="/media/usbstick/GnuPlot/gnuplot_config_asele.plt"
# Plot für Wetter der letzten 30 Tage als PNG erzeugen:
# Dateiname für Plot einstellen:
filename="/media/usbstick/GnuPlot/wettergraph_gnuplot_asele_4_weeks.jpg"
filenametext="set output '"$filename"'"
# Dateinamen in Config Zeile 53 schreiben:
sed -i 53d $configdatei
sed -i "53i$filenametext" $configdatei
# Datumsgrenzen einstellen:
ausschnitt="set xrange [\""$datum_letzter_monat"\":\""$datum_heute"\"]"
# Datumsgrenzen in Config Zeile 15 und 81 schreiben:
sed -i 15d $configdatei
sed -i "15i$ausschnitt" $configdatei
sed -i 81d $configdatei
sed -i "81i$ausschnitt" $configdatei
# Plot durchführen:
gnuplot -persist $configdatei
# Watermarks setzen
composite -dissolve 80% -quality 100 -geometry +10+2 $wasserzeichen_1 $filename $filename
composite -dissolve 80% -quality 100 -geometry +1000+2 $wasserzeichen_2 $filename $filename

# Plot für Wetter der letzten 6 Monate als PNG erzeugen:
# Dateiname für Plot einstellen:
filename="/media/usbstick/GnuPlot/wettergraph_gnuplot_asele_6_months.jpg"
filenametext="set output '"$filename"'"
# Dateinamen in Config Zeile 53 schreiben:
sed -i 53d $configdatei
sed -i "53i$filenametext" $configdatei
# Datumsgrenzen einstellen:
ausschnitt="set xrange [\""$datum_letzte_sechs_monate"\":\""$datum_heute"\"]"
# Datumsgrenzen in Config Zeile 15 und 81 schreiben:
sed -i 15d $configdatei
sed -i "15i$ausschnitt" $configdatei
sed -i 81d $configdatei
sed -i "81i$ausschnitt" $configdatei
# Plot durchführen:
gnuplot -persist $configdatei
# Watermarks setzen
composite -dissolve 80% -quality 100 -geometry +10+2 $wasserzeichen_1 $filename $filename
composite -dissolve 80% -quality 100 -geometry +1000+2 $wasserzeichen_2 $filename $filename

# Plot für Wetter des letzten Jahres als PNG erzeugen:
# Dateiname für Plot einstellen:
filename="/media/usbstick/GnuPlot/wettergraph_gnuplot_asele_12_months.jpg"
filenametext="set output '"$filename"'"
# Dateinamen in Config Zeile 53 schreiben:
sed -i 53d $configdatei
sed -i "53i$filenametext" $configdatei
# Datumsgrenzen einstellen:
ausschnitt="set xrange [\""$datum_letztes_jahr"\":\""$datum_heute"\"]"
# Datumsgrenzen in Config Zeile 15 und 81 schreiben:
sed -i 15d $configdatei
sed -i "15i$ausschnitt" $configdatei
sed -i 81d $configdatei
sed -i "81i$ausschnitt" $configdatei
# Plot durchführen:
gnuplot -persist $configdatei
# Watermarks setzen
composite -dissolve 80% -quality 100 -geometry +10+2 $wasserzeichen_1 $filename $filename
composite -dissolve 80% -quality 100 -geometry +1000+2 $wasserzeichen_2 $filename $filename

echo "Berechnungen der Plots für Asele abgeschlossen."

################### Grafikplots für Berchtesgaden erzeugen #######################
# Es muss jeweils das Datum und der Dateiname in der Config angepaßt werden
# bevor der Plot durchgeführt wird
echo "Starte Berechnung der Plots für Berchtesgaden..."
# Configdatei ändern
configdatei="/media/usbstick/GnuPlot/gnuplot_config_bgd.plt"
# Plot für Wetter der letzten 30 Tage als PNG erzeugen:
# Dateiname für Plot einstellen:
filename="/media/usbstick/GnuPlot/wettergraph_gnuplot_bgd_4_weeks.jpg"
filenametext="set output '"$filename"'"
# Dateinamen in Config Zeile 53 schreiben:
sed -i 53d $configdatei
sed -i "53i$filenametext" $configdatei
# Datumsgrenzen einstellen:
ausschnitt="set xrange [\""$datum_letzter_monat"\":\""$datum_heute"\"]"
# Datumsgrenzen in Config Zeile 15 und 81 schreiben:
sed -i 15d $configdatei
sed -i "15i$ausschnitt" $configdatei
sed -i 81d $configdatei
sed -i "81i$ausschnitt" $configdatei
# Plot durchführen:
gnuplot -persist $configdatei
# Watermarks setzen
composite -dissolve 80% -quality 100 -geometry +10+2 $wasserzeichen_1 $filename $filename
composite -dissolve 80% -quality 100 -geometry +1000+2 $wasserzeichen_2 $filename $filename

# Plot für Wetter der letzten 6 Monate als PNG erzeugen:
# Dateiname für Plot einstellen:
filename="/media/usbstick/GnuPlot/wettergraph_gnuplot_bgd_6_months.jpg"
filenametext="set output '"$filename"'"
# Dateinamen in Config Zeile 53 schreiben:
sed -i 53d $configdatei
sed -i "53i$filenametext" $configdatei
# Datumsgrenzen einstellen:
ausschnitt="set xrange [\""$datum_letzte_sechs_monate"\":\""$datum_heute"\"]"
# Datumsgrenzen in Config Zeile 15 und 81 schreiben:
sed -i 15d $configdatei
sed -i "15i$ausschnitt" $configdatei
sed -i 81d $configdatei
sed -i "81i$ausschnitt" $configdatei
# Plot durchführen:
gnuplot -persist $configdatei
# Watermarks setzen
composite -dissolve 80% -quality 100 -geometry +10+2 $wasserzeichen_1 $filename $filename
composite -dissolve 80% -quality 100 -geometry +1000+2 $wasserzeichen_2 $filename $filename

# Plot für Wetter des letzten Jahres als PNG erzeugen:
# Dateiname für Plot einstellen:
filename="/media/usbstick/GnuPlot/wettergraph_gnuplot_bgd_12_months.jpg"
filenametext="set output '"$filename"'"
# Dateinamen in Config Zeile 53 schreiben:
sed -i 53d $configdatei
sed -i "53i$filenametext" $configdatei
# Datumsgrenzen einstellen:
ausschnitt="set xrange [\""$datum_letztes_jahr"\":\""$datum_heute"\"]"
# Datumsgrenzen in Config Zeile 15 und 81 schreiben:
sed -i 15d $configdatei
sed -i "15i$ausschnitt" $configdatei
sed -i 81d $configdatei
sed -i "81i$ausschnitt" $configdatei
# Plot durchführen:
gnuplot -persist $configdatei
# Watermarks setzen
composite -dissolve 80% -quality 100 -geometry +10+2 $wasserzeichen_1 $filename $filename
composite -dissolve 80% -quality 100 -geometry +1000+2 $wasserzeichen_2 $filename $filename

echo "Berechnungen der Plots für Berchtesgaden abgeschlossen."

################################################
# Upload der JPGs auf den Webspace
################################################
echo "Starte Upload der Plots auf den Server..."
HOST='**************'
USER='******************'
PASSWD='****************'

cd /media/usbstick/GnuPlot  # In den lokalen Ordner auf dem USB-Stick wechseln
ftp -n -v $HOST << EOT
ascii
user $USER $PASSWD
cd /WordPress_01/wp-content/uploads/gnuplot # In den Ordner auf dem FTP-Server wechseln
prompt
mput *.jpg
bye
EOT
echo "Upload der Plots auf den Server abgeschlossen. Script komplett abgearbeitet."

Und ausführbar machen:

sudo chmod +x /home/pi/Scripts/GnuPlot/generate_gnuplots.sh

In diesem Beispielscript werden die Wetterdaten aus Log-Dateien von zwei Orten verwendet, das PLT-Script von GnuPlot angepaßt, dann der Plot ausgeführt, die Grafiken mit Wasserzeichen versehen und auf den Webspace geladen. Für jeden Ort legt man ein PLT-Script an. Hier folgen meine beiden Beispiele:

nano /media/usbstick/GnuPlot/gnuplot_config_asele.plt
#Gnuplot script
#Generierung des Plots für den Wetterverlauf in Asele, Schweden
#Matthias Pfeifer

set encoding utf8
set datafile separator ";"
set grid
set xdata time 
set timefmt "%d.%m.%Y" 
set format x "%d.%m.%Y"
set autoscale 

# Einstellungen für Graph 1:
# Zeitachse:
set xrange ["17.07.2015":"17.07.2016"]
#set xtics "01.01.2016", 1209600, "31.12.2016" #Der mittlere Wert gibt den Tic in Sekunden an!
set xtics format "%b %d"
set ytics nomirror
# Temperaturachse (links):
set yrange [-30:35]
set ytics -30,5,35
set mytics 5
# Luftfeuchtigkeitsachse (rechts):
set y2range [0:100]
set y2tics 0,10,100
set my2tics 5

# Tabelleneigenschaften allgemein:
set title "Temperatur und Luftfeuchtigkeit"
set ylabel "Temperatur [°C]"
set y2label "Luftfeuchtigkeit [%]"
#set xlabel "Datum"

### Farbstile setzen ###
set style line 1 lt 22 lc rgb "orange-red" lw 1
set style line 2 lt 4 lc rgb "orange" lw 1
set style line 3 lt 11 lc rgb "blue" lw 1
set style line 4 lt 19 lc rgb "green" lw 1
set style line 5 lt 17 lc rgb "blue" lw 1
set style line 6 lt 1 lc rgb "sea-green" lw 1
set boxwidth 0.75 relative #Balken mit 75% Breite
set style fill transparent solid 0.5 #Balken halbtransparent
### Output setzen ###
#Für EPS:
#set terminal postscript eps enhanced color dl 2.0 size 1000,1000 "Helvetica" 12
#set encoding iso_8859_1
#set tics scale 1.5
#Für PNG:
#set terminal png truecolor size 800,1200 crop font "arial,10" background rgb "gray90"
#set output '/media/usbstick/GnuPlot/nxm_plot.png'
#Für JPG:
set terminal jpeg enhanced size 1200,1800 crop font "arial,10" background rgb "gray90"
set output '/media/usbstick/GnuPlot/wettergraph_gnuplot_asele_12_months.jpg'

### Multiplot-Einstellungen ###
set multiplot layout 3,1 title "Wetterdaten aus Asele"
set key outside horizontal bottom center #Position dr Legende
### Graph 1 plotten (Maximal-, Mimimaltemperatur, Luftfeuchtigkeit ###
plot "/media/usbstick/Wetter/wetterlog_gnuplot_asele.csv" using 1:6 title'Maximaltemperatur' with linespoints axes x1y1 ls 1 smooth csplines, \
"/media/usbstick/Wetter/wetterlog_gnuplot_asele.csv" using 1:12 title 'Durchschnittstemperatur' with linespoints axes x1y1 ls 4 smooth csplines, \
"/media/usbstick/Wetter/wetterlog_gnuplot_asele.csv" using 1:7 title 'Minimaltemperatur' with linespoints axes x1y1 ls 3 smooth csplines, \
"/media/usbstick/Wetter/wetterlog_gnuplot_asele.csv" using 1:5 title 'Luftfeuchtigkeit' with linespoints axes x1y2 ls 6 smooth csplines
unset label
unset y2label
unset y2range
unset y2tics

#Einstellungen für Graph 2:
set title "Sonnenauf- und Sonnenuntergang"
#set xlabel "Datum"
set ylabel "Uhrzeit"
set yrange [0:24]
set ytics 0,1,24
set mytics 6
set y2label "Sonnenminuten"
set y2range [0:1440]
set y2tics 0,60,1440
#set my2tics 5
set xdata time
set timefmt "%d.%m.%Y"
set xrange ["17.07.2015":"17.07.2016"]
set xtics format "%b %d"
set style fill solid 0.3

### Graph 2 plotten (Sonnenauf- und Untergang) ###
plot "/media/usbstick/Wetter/wetterlog_gnuplot_asele.csv" using 1:15 title 'Sonnenstunden' with boxes axes x1y2 ls 2, \
"/media/usbstick/Wetter/wetterlog_gnuplot_asele.csv" using 1:13 title 'Sonnenaufgang' with linespoints axes x1y2 ls 4 smooth csplines, \
"/media/usbstick/Wetter/wetterlog_gnuplot_asele.csv" using 1:14 title 'Sonnenuntergang' with linespoints axes x1y2 ls 5 smooth csplines

### Multiplot beenden ###
unset multiplot

Und die PLT-Datei für den zweiten Ort:

nano /media/usbstick/GnuPlot/gnuplot_config_bgd.plt
#Gnuplot script
#Generierung des Plots für den Wetterverlauf in Berchtesgaden, Deutschland
#Matthias Pfeifer

set encoding utf8
set datafile separator ";"
set grid
set xdata time 
set timefmt "%d.%m.%Y" 
set format x "%d.%m.%Y"
set autoscale 

# Einstellungen für Graph 1:
# Zeitachse:
set xrange ["17.07.2015":"17.07.2016"]
set xtics format "%b %d"
set ytics nomirror
# Temperaturachse (links):
set yrange [-20:35]
set ytics -20,5,35
set mytics 5
# Luftfeuchtigkeitsachse (rechts):
set y2range [0:100]
set y2tics 0,10,100
set my2tics 5

# Tabelleneigenschaften allgemein:
set title "Temperatur und Luftfeuchtigkeit"
set ylabel "Temperatur [°C]"
set y2label "Luftfeuchtigkeit [%]"
#set xlabel "Datum"

### Farbstile setzen ###
set style line 1 lt 22 lc rgb "orange-red" lw 1
set style line 2 lt 4 lc rgb "orange" lw 1
set style line 3 lt 11 lc rgb "blue" lw 1
set style line 4 lt 19 lc rgb "green" lw 1
set style line 5 lt 17 lc rgb "blue" lw 1
set style line 6 lt 1 lc rgb "sea-green" lw 1
set boxwidth 0.75 relative #Balken mit 75% Breite
set style fill transparent solid 0.5 #Balken halbtransparent und ohne Rand
### Output setzen ###
#Für EPS:
#set terminal postscript eps enhanced color dl 2.0 size 1000,1000 "Helvetica" 12
#set encoding iso_8859_1
#set tics scale 1.5
#Für PNG:
#set terminal png truecolor size 800,1200 crop font "arial,10" background rgb "gray90"
#set output '/media/usbstick/GnuPlot/nxm_plot.png'
#Für JPG:
set terminal jpeg enhanced size 1200,1800 crop font "arial,10" background rgb "gray90"
set output '/media/usbstick/GnuPlot/wettergraph_gnuplot_bgd_12_months.jpg'
set output '/media/usbstick/GnuPlot/wettergraph_gnuplot_bgd_12_months.jpg'
### Multiplot-Einstellungen ###
set multiplot layout 3,1 title "Wetterdaten aus Berchtesgaden"
set key outside horizontal bottom center #Position dr Legende
### Graph 1 plotten (Maximal-, Mimimaltemperatur, Luftfeuchtigkeit ###
plot "/media/usbstick/Wetter/wetterlog_gnuplot_bgd.csv" using 1:6 title 'Maximaltemperatur' with linespoints axes x1y1 ls 1 smooth csplines, \
"/media/usbstick/Wetter/wetterlog_gnuplot_bgd.csv" using 1:12 title 'Durchschnittstemperatur' with linespoints axes x1y1 ls 4 smooth csplines, \
"/media/usbstick/Wetter/wetterlog_gnuplot_bgd.csv" using 1:7 title 'Minimaltemperatur' with linespoints axes x1y1 ls 3 smooth csplines, \
"/media/usbstick/Wetter/wetterlog_gnuplot_bgd.csv" using 1:5 title 'Luftfeuchtigkeit' with linespoints axes x1y2 ls 6 smooth csplines
unset label
unset y2label
unset y2range
unset y2tics

#Einstellungen für Graph 2:
set title "Sonnenauf- und Sonnenuntergang"
#set xlabel "Datum"
set ylabel "Uhrzeit"
set yrange [0:24]
set ytics 0,1,24
set mytics 6
set y2label "Sonnenminuten"
set y2range [0:1440]
set y2tics 0,60,1440
#set my2tics 5
set xdata time
set timefmt "%d.%m.%Y"
set xtics format "%b %d"
set xrange ["17.07.2015":"17.07.2016"]
set style fill solid 0.3

### Graph 2 plotten (Sonnenauf- und Untergang) ###
plot "/media/usbstick/Wetter/wetterlog_gnuplot_bgd.csv" using 1:15 title 'Sonnenstunden' with boxes axes x1y2 ls 2, \
"/media/usbstick/Wetter/wetterlog_gnuplot_bgd.csv" using 1:13 title'Sonnenaufgang' with linespoints axes x1y2 ls 4 smooth csplines, \
"/media/usbstick/Wetter/wetterlog_gnuplot_bgd.csv" using 1:14 title 'Sonnenuntergang' with linespoints axes x1y2 ls 5 smooth csplines

### Multiplot beenden ###
unset multiplot

Beide PLT-Dateien sollten von der Zeilenposition her nicht verändert werden, da einzelne Zeilen automatisch abgeändert werden um die Plots für den 4-Wochen-, 6-Monats- und Jahresverlauf zu berechnen. Weiterhin müssen in folgendem Ordner die Wasserzeichen abgelegt werden (in meinem Beispiel eine PNG von Wunderground sowie meine eigene:

mkdir /media/usbstick/GnuPlot/Wasserzeichen

Nun benötigen wir noch jeweils ein Script, welches uns einmal am Tag die Wetterdaten von Underground holt und in eine Log-Datei einträgt.

Hier das erste Script:

nano /home/pi/Scripts/Wetter/get_weather_gnuplot_asele.py
#!/usr/bin/python3 
# -*- coding: utf-8 -*-

# Script um einmal am Tag die Wetterdaten von Wunderground zu holen und
# in eine Datei für Gnuplot zu schreiben. 

# Module laden
import sys;
reload (sys);
sys.setdefaultencoding("utf8")
from time import *
from shutil import copyfile
import requests,urllib2,json,os.path,io,datetime

# Variablen anlegen:
key = "****************" #API-Key bei Wunderground
ort = "Asele" #Ort der Abfrage
land = "Sweden" #Land der Abfrage
wetterdatei = "/media/usbstick/Wetter/wetterlog_gnuplot_asele.csv" #Pfad zur Datendatei
backupordner = "/media/usbstick/Wetter/Backup_Asele" #Ordner für Backup der Datendatei

# Ab hier muss nichts mehr verändert werden:
liste = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] #Array für die aktuellen Wetterdaten
degreeChar = u'\N{DEGREE SIGN}' #Gradzeichen erzeugen
fcast = []
# Aktuelles Datum und Uhrzeit
lt = localtime()
datum = strftime("%d.%m.%Y", lt)
zeit = strftime("%H:%M", lt)
# Pfad zur Backup-Datei erstellen:
timestamp = strftime("%Y_%m_%d", lt)

# Hier startet das Hauptprogramm:
print("Hole Daten von Wunderground...")

# Wetterdaten aktuell bei Wunderground abholen
url = 'http://api.wunderground.com/api/' + key + '/geolookup/conditions/lang:DL/q/' + land + '/' + ort + '.json'
f = urllib2.urlopen(url)
json_string = f.read()
parsed_json = json.loads(json_string)
city = parsed_json['location']['city']
state = parsed_json['location']['state']
weather = parsed_json['current_observation']['weather']
temperature_string = parsed_json['current_observation']['temperature_string']
feelslike_string = parsed_json['current_observation']['feelslike_string']

# Aktuellen Ort holen:
location = parsed_json['location']['city']

# Aktuelle Temperatur in Grad holen:
temp_c = parsed_json['current_observation']['temp_c']

# Aktuelle Luftfeuchtigkeit in Prozent holen
hum = parsed_json['current_observation']['relative_humidity']

f.close()

# Vorhersage holen:
url = 'http://api.wunderground.com/api/' + key + '/forecast/astronomy/lang:DL/q/' + land + '/' + ort + '.json'
r = requests.get(url)
data=r.json() # data contains the parsed JSON string
r.close()
i=0
for day in data['forecast']['simpleforecast']['forecastday']:
 x=day['date']['weekday_short'] + ":"
 y=day['conditions']
 z = day['high']['celsius'] + degreeChar+"C/" + day['low']['celsius'] + degreeChar+"C"
 fcast.append(x + " " + y + " " + z)
 if i==0:
 # Maximale Tagestemperatur holen:
 temp_max=day['high']['celsius']
 # Minimale Tagestemperatur holen:
 temp_min=day['low']['celsius']
 # Wettertext holen:
 condition=day['conditions']
 condition=condition.replace(" ", "_") # Leerzeichen gegen _ austauschen, sonst gibts Probleme in der Bash
 # Sonnenaufgang holen:
 sunrise_hour = data['sun_phase']['sunrise']['hour']
 sunrise_minute = data['sun_phase']['sunrise']['minute']
 a = int(sunrise_hour)
 b = int(sunrise_minute)
 sunrise_in_minutes = str((a*60)+b)
 sunrise = str(sunrise_hour + ":" + sunrise_minute)
 # Sonnenuntergang holen:
 sundown_hour = data['sun_phase']['sunset']['hour']
 sundown_minute = data['sun_phase']['sunset']['minute']
 a = int(sundown_hour)
 b = int(sundown_minute)
 sundown_in_minutes = str((a*60)+b)
 sundown = str(sundown_hour + ":" + sundown_minute)
 i=i+1

# Sonnenstunden pro Tag berechnen
a = datetime.datetime.strptime(sunrise, '%H:%M')
b = datetime.datetime.strptime(sundown, '%H:%M')
c = b - a
Sonnenstunden=str(c) #Zeit in String umwandeln
Sonnenstunden=(Sonnenstunden[:5]) #Sekunden abschneiden
# Sonnenminuten pro Tag berechnen
a = int(Sonnenstunden[0:2]) #Stundenzahl
b = int(Sonnenstunden[4:5]) #Minutenzahl
c = ((a*60)+b)
Sonnenminuten=str(c) #Zeit in String umwandeln

# Mittelwert Minimal-/Maximaltemperatur berechnen
temp_min_int = float(temp_min) #String in Fließkomma umwandeln
temp_max_int = float(temp_max) #String in Fließkomma umwandeln
e=((temp_min_int+temp_max_int)/2) #Mittelwert berechnen
Durchschnittstemperatur = str(e) #Mittelwert in String umwandeln

# Wetterdaten in Liste schreiben:
liste[0] = datum #Datum
liste[1] = zeit #Zeit
liste[2] = location #Ort
liste[3] = temp_c #Aktuelle Temperatur
liste[4] = hum #Luftfeuchtigkeit
liste[5] = temp_max #Tagesmaximaltemperatur
liste[6] = temp_min #Tagesminimaltemperatur
liste[7] = sunrise #Sonnenaufgang
liste[8] = sundown #Sonnenuntergang
liste[9] = condition #Wetterbedingungen
liste[10] = Sonnenstunden #Sonnenstunden
liste[11] = Durchschnittstemperatur #Durchschnittstemperatur
liste[12] = sunrise_in_minutes #Sonnenaufgang in Minuten
liste[13] = sundown_in_minutes #Sonnenuntergang in Minuten
liste[14] = Sonnenminuten #Sonnenminuten

# Zeile für Wetterdatei generieren:
line = (str(liste[0])+";"+str(liste[1])+";"+str(liste[2])+";"+str(liste[3])+ \
 ";"+str(liste[4])+";"+str(liste[5])+";"+str(liste[6])+";"+str(liste[7])+ \
 ";"+str(liste[8])+";"+str(liste[9])+";"+str(liste[10])+";"+str(liste[11])+ \
 ";"+str(liste[12])+";"+str(liste[13])+";"+str(liste[14]))

# Falls Wetterdatei noch nicht existiert, diese anlegen:
if not os.path.exists(wetterdatei):
 fout=open(wetterdatei,"w")
 fout.close()
 print("Habe keine Wetterdatei im Verzeichnis gefunden - neue Datei angelegt")

# Backup Wetterdatei anlegen:
backupdatei=str(backupordner + '/' + timestamp + '_backup_gnuplot.csv')
if not os.path.exists(backupdatei): #Nur einmal am Tag Backup anlegen, falls Datei noch nicht existiert
 copyfile(wetterdatei,backupdatei)
 print("Backup erstellt in " + backupdatei)
else:
 print("Backup wurde heute schon einmal erstellt - Skipped")

# Zeile an Wetterdatei anhängen:
fout=open(wetterdatei,"a")
fout.writelines(line + '\n')
fout.close()
print(wetterdatei+" wurde ergänzt.")
print("Die neue Zeile sieht so aus:\n" + line)

# Programm wird beendet:
print("Programm vollständig abgearbeitet.")

Das Ganze natürlich wieder ausführbar machen. Dann das zweite Script:

nano /home/pi/Scripts/Wetter/get_weather_gnuplot_bgd.py
#!/usr/bin/python3 
# -*- coding: utf-8 -*-

# Script um einmal am Tag die Wetterdaten von Wunderground zu holen und
# in eine Datei für Gnuplot zu schreiben. 

# Module laden
import sys;
reload (sys);
sys.setdefaultencoding("utf8")
from time import *
from shutil import copyfile
import requests,urllib2,json,os.path,io,datetime

# Variablen anlegen:
key = "*****************" #API-Key bei Wunderground
ort = "Berchtesgaden" #Ort der Abfrage
land = "Germany" #Land der Abfrage
wetterdatei = "/media/usbstick/Wetter/wetterlog_gnuplot_bgd.csv" #Pfad zur Datendatei
backupordner = "/media/usbstick/Wetter/Backup_BGD" #Ordner für Backup der Datendatei

# Ab hier muss nichts mehr verändert werden:
liste = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] #Array für die aktuellen Wetterdaten
degreeChar = u'\N{DEGREE SIGN}' #Gradzeichen erzeugen
fcast = []
# Aktuelles Datum und Uhrzeit
lt = localtime()
datum = strftime("%d.%m.%Y", lt)
zeit = strftime("%H:%M", lt)
# Pfad zur Backup-Datei erstellen:
timestamp = strftime("%Y_%m_%d", lt)

# Hier startet das Hauptprogramm:
print("Hole Daten von Wunderground...")

# Wetterdaten aktuell bei Wunderground abholen
url = 'http://api.wunderground.com/api/' + key + '/geolookup/conditions/lang:DL/q/' + land + '/' + ort + '.json'
f = urllib2.urlopen(url)
json_string = f.read()
parsed_json = json.loads(json_string)
city = parsed_json['location']['city']
state = parsed_json['location']['state']
weather = parsed_json['current_observation']['weather']
temperature_string = parsed_json['current_observation']['temperature_string']
feelslike_string = parsed_json['current_observation']['feelslike_string']

# Aktuellen Ort holen:
location = parsed_json['location']['city']

# Aktuelle Temperatur in Grad holen:
temp_c = parsed_json['current_observation']['temp_c']

# Aktuelle Luftfeuchtigkeit in Prozent holen
hum = parsed_json['current_observation']['relative_humidity']

f.close()

# Vorhersage holen:
url = 'http://api.wunderground.com/api/' + key + '/forecast/astronomy/lang:DL/q/' + land + '/' + ort + '.json'
r = requests.get(url)
data=r.json() # data contains the parsed JSON string
r.close()
i=0
for day in data['forecast']['simpleforecast']['forecastday']:
 x=day['date']['weekday_short'] + ":"
 y=day['conditions']
 z = day['high']['celsius'] + degreeChar+"C/" + day['low']['celsius'] + degreeChar+"C"
 fcast.append(x + " " + y + " " + z)
 if i==0:
 # Maximale Tagestemperatur holen:
 temp_max=day['high']['celsius']
 # Minimale Tagestemperatur holen:
 temp_min=day['low']['celsius']
 # Wettertext holen:
 condition=day['conditions']
 condition=condition.replace(" ", "_") # Leerzeichen gegen _ austauschen, sonst gibts Probleme in der Bash
 # Sonnenaufgang holen:
 sunrise_hour = data['sun_phase']['sunrise']['hour']
 sunrise_minute = data['sun_phase']['sunrise']['minute']
 a = int(sunrise_hour)
 b = int(sunrise_minute)
 sunrise_in_minutes = str((a*60)+b)
 sunrise = str(sunrise_hour + ":" + sunrise_minute)
 # Sonnenuntergang holen:
 sundown_hour = data['sun_phase']['sunset']['hour']
 sundown_minute = data['sun_phase']['sunset']['minute']
 a = int(sundown_hour)
 b = int(sundown_minute)
 sundown_in_minutes = str((a*60)+b)
 sundown = str(sundown_hour + ":" + sundown_minute)
 i=i+1

# Sonnenstunden pro Tag berechnen
a = datetime.datetime.strptime(sunrise, '%H:%M')
b = datetime.datetime.strptime(sundown, '%H:%M')
c = b - a
Sonnenstunden=str(c) #Zeit in String umwandeln
Sonnenstunden=(Sonnenstunden[:5]) #Sekunden abschneiden
# Sonnenminuten pro Tag berechnen
a = int(Sonnenstunden[0:2]) #Stundenzahl
b = int(Sonnenstunden[4:5]) #Minutenzahl
c = ((a*60)+b)
Sonnenminuten=str(c) #Zeit in String umwandeln

# Mittelwert Minimal-/Maximaltemperatur berechnen
temp_min_int = float(temp_min) #String in Fließkomma umwandeln
temp_max_int = float(temp_max) #String in Fließkomma umwandeln
e=((temp_min_int+temp_max_int)/2) #Mittelwert berechnen
Durchschnittstemperatur = str(e) #Mittelwert in String umwandeln

# Wetterdaten in Liste schreiben:
liste[0] = datum #Datum
liste[1] = zeit #Zeit
liste[2] = location #Ort
liste[3] = temp_c #Aktuelle Temperatur
liste[4] = hum #Luftfeuchtigkeit
liste[5] = temp_max #Tagesmaximaltemperatur
liste[6] = temp_min #Tagesminimaltemperatur
liste[7] = sunrise #Sonnenaufgang
liste[8] = sundown #Sonnenuntergang
liste[9] = condition #Wetterbedingungen
liste[10] = Sonnenstunden #Sonnenstunden
liste[11] = Durchschnittstemperatur #Durchschnittstemperatur
liste[12] = sunrise_in_minutes #Sonnenaufgang in Minuten
liste[13] = sundown_in_minutes #Sonnenuntergang in Minuten
liste[14] = Sonnenminuten #Sonnenminuten

# Zeile für Wetterdatei generieren:
line = (str(liste[0])+";"+str(liste[1])+";"+str(liste[2])+";"+str(liste[3])+ \
 ";"+str(liste[4])+";"+str(liste[5])+";"+str(liste[6])+";"+str(liste[7])+ \
 ";"+str(liste[8])+";"+str(liste[9])+";"+str(liste[10])+";"+str(liste[11])+ \
 ";"+str(liste[12])+";"+str(liste[13])+";"+str(liste[14]))
# Falls Wetterdatei noch nicht existiert, diese anlegen:
if not os.path.exists(wetterdatei):
 fout=open(wetterdatei,"w")
 fout.close()
 print("Habe keine Wetterdatei im Verzeichnis gefunden - neue Datei angelegt")

# Backup Wetterdatei anlegen:
backupdatei=str(backupordner + '/' + timestamp + '_backup_gnuplot.csv')
if not os.path.exists(backupdatei): #Nur einmal am Tag Backup anlegen, falls Datei noch nicht existiert
 copyfile(wetterdatei,backupdatei)
 print("Backup erstellt in " + backupdatei)
else:
 print("Backup wurde heute schon einmal erstellt - Skipped")

# Zeile an Wetterdatei anhängen:
fout=open(wetterdatei,"a")
fout.writelines(line + '\n')
fout.close()
print(wetterdatei+" wurde ergänzt.")
print("Die neue Zeile sieht so aus:\n" + line)

# Programm wird beendet:
print("Programm vollständig abgearbeitet.")

Aus dieses Script wieder ausführbar machen.

Was nun noch fehlt, sind entsprechende Einträge in der Crontab:

sudo crontab -e
# Jeden Tag um 12:25 Uhr einmal Wetterdaten in Asele von Wunderground für GnuPlot holen:
25 12 * * * /usr/bin/python2 /home/pi/Scripts/Wetter/get_weather_gnuplot_asele.py

# Jeden Tag um 12:25 Uhr einmal Wetterdaten in Berchtesgaden von Wunderground für GnuPlot holen:
25 12 * * * /usr/bin/python2 /home/pi/Scripts/Wetter/get_weather_gnuplot_bgd.py

# Jeden Tag um 12:28 Uhr einmal GnuPlots der Wetterdaten neu generieren und hochladen:
28 12 * * * /bin/bash /home/pi/Scripts/GnuPlot/generate_gnuplots.sh

Nun müsst Ihr nur noch die JPG´s der Plots auf Eurer Webseite einbinden. Wie die Plots aussehen, wenn es viele Werte gibt kann ich allerdings noch nicht sagen. Mal sehen, ob man noch alles gut erkennen kann!

Befestigung der Cam

Ich habe mich wie auf dem Beitragsbild zu sehen für eine Bastellösung mithilfe einer ausgemusterten Handhalterung fürs Auto entschieden. Hatte ich noch zu Hause rumliegen und funktioniert mithilfe zweier Kabelbinder wunderbar. Den WLAN-Stick habe ich an ein Verlängerungs-USB-Kabel gehängt, damit das Blinklicht des Sticks in der Dämmerung nicht die Aufnahme kaputtmacht (Spiegelung in der Fensterscheibe). Als Case für den RasPi dient diese Hülle mit integriertem Halter für die RasPiCam. Am Fenster hält das Ganze bombig.

RaspiCam

Fazit

So, dass wars. Mit wenig Aufwand habt Ihr ein eine tolle Webcam, die komplett autark arbeitet, automatisch Fotos twittert, mit der aktuellen Wettervorhersage versieht, auf den WebSpace hochläd und Euch Aufnahmen für die Erstellung einer Zeitrafferaufnahme liefert. Ein kostenloses Programm, um aus den Einzelbildern ein Video zu basteln ist auf dem Mac „Time Lapse Assembler„. Selbstverständlich könnte man die Fotos auch auf einen USB-Stick speichern und vom Raspberry in ein Video umwandeln lassen. Aber das überlasse ich Eurer Fantasie… Viel Spaß beim Basteln!

Hat hoffentlich alles funktioniert? Ich freue mich auf Euer Feedback (da gibt´s leider viel zu wenig davon…)!


Quellen

bubuxblog, AngInf, Good To Know Database, chrisge.org

3 Antworten

  1. Ron sagt:

    Sehr interessantes Projekt, vielen Dank. Werde es für einen Hausbau im Herbst nutzen um den Baufortschritt zu dokumentieren. Habe auch eine Synology, da muss ich mich aber noch etwas einlesen, was den FTP User betrifft.

    Ein Erweiterungsvorschlag hätte ich noch. Die Nutzung eines GPIO Eingangs zum triggern von Bildern. So das entweder in Zeitintervallen oder bei Auslösung durch Kontakt / Bewegungsmelder Bilder entsprechend gespeichert und per twitter gesendet werden.

    • Matthias sagt:

      Hallo Ron,
      der FTP-Server auf der Syno ist einfach unter „Dateidienste“ zu aktivieren. Da Du ihn ja nur in Deinem lokalen Netzwerk verwendest, brauchst Du auch keinen Port „nach draußen“ öffnen. Am besten legst Du Dir noch einen gemeinsamen Ordner (zB. „FTP“) und einen Nutzer an (zB. „ftpuser“), dem Du nur Rechte für den FTP-Ordner und den FTP-Dienst gibst. Und auf der Firewall der Syno sollte der FTP-Dienst durchgelassen werden.
      Dein Vorschlag ist gut, leider kenne ich mich mit der „Elektrik-Bastelei“ noch nicht wirklich aus… Das wird wohl was für die kommenden langen Winterabende
      Liebe Grüße!

  2. Schmid sagt:

    Weltklasse, habe einiges für mich verwenden können und dich auch in dem Forum genannt in welchem ich mein Projekt unterhalte. Schildkröten-Gehege-Steuerung -> http://www.testudo-forum.de/wbb/index.php?page=Thread&postID=258695#post258695

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

fünf × vier =

%d Bloggern gefällt das: