Praxis

Raspberry Pi - Bewegungsmelder-Code

Raspberry Pi

Die Anleitung ergänzt die Artikelserie über die Raspberry-Pi-Kamera ab FOTO HITS 12/2016. Auf dieser Seite kann man den Code kopieren, der den Bewegungsmelder steuert, ein Foto schießt und es verschickt. 

Bild
Mit dem IR-Kamera-Modul (ebenfalls um 30 Euro) kann man sogar das Innere eines Nistkastens überwachen.

Die Redaktion empfiehlt, das fertige Skript motion.py herunterzuladen. Nach einem Rechtsklick auf den folgenden Link bietet das Kontextmenü je nach Browser etwa an: "Link speichern unter ...": Download Code

Wichtig ist:

  1. Niemals den Code in einem Textverarbeitungssystem bearbeiten. Dafür darf nur ein Text-Editor verwendet werden, wie ihn Rasperry unter "Zubehör - Editor" bereitstellt.
  2. Am einfachsten markiert man die Zeilen unten mit dem Mauszeiger und kopiert sie etwa mit dem Tastenbefehl Strg und c. Dann werden sie etwa mit Strg und v in den Texteditor eingefügt.
  3. Die Zeilen müssen so wie auf der Website gezeigt eingerückt werden. Das darf keinesfalls per Leerzeichen geschehen, sondern es muss die Tab-Taste links oben auf der Tastatur genutzt werden – „Python“ ist hier eigen. Wer das Skript unten kopiert, entfernt sicherheitshalber zuerst die Einrückungen, falls sie aus Leerzeichen bestehen. Dann drückt man etwa bei "fp = open" ein Mal die Tab-Taste, bei "fp = read" zwei Mal die Tab-Taste. 
  4. Das Ergebnis erhält etwa den Dateinamen motion.py.

Nachfolgend steht der Code auch zum Kopieren bereit. Wichtig ist, etwa die Angaben zum E-Mail-Versand einzutragen. Sie und weitere Anpassungen werden unterhalb des Skripts erläutert.

#!/usr/bin/env python
# coding: utf8

# Import der Python libraries
import RPi.GPIO as GPIO
import time
import datetime
import picamera
import smtplib

from os.path import basename
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart

# Wir verwenden den Board Mode, Angabe der PIN Nummern anstelle der GPIO BCM Nummer
GPIO.setmode(GPIO.BOARD)
# GPIO definieren
GPIO_PIR = 7
# GPIO als "Input" definieren
GPIO.setup(GPIO_PIR, GPIO.IN)

# Speicherort definieren
STORAGE_LOCATION = '/home/pi/Desktop/'

# Timeouts definieren
TIMEOUT_AFTER_CAPTURE = 10
TIMEOUT_BETWEEN_CAPTURE = 1

# Anzahl der Bilder die durch eine Bewegung aufgezeichnet werden
CAPTURE_COUNT = 5

# Größe der Bilder definieren
PIC_WIDTH = 1280
PIC_HEIGHT = 1024

# Soll eine Mail gesendet werden?
SEND_EMAIL = 1

# SMTP Einstellungen definieren
smtp_host = 'smtp.server.de'
smtp_port = 587
smtp_user = 'username'
smtp_pass = 'password'

# Absender und Empfänger für Mail definieren
subject = 'Bewegungsmelder ausgelöst'
addr_from = 'from@mail.de'
addr_to = 'to@mail.de'

# Kamera initialisieren
camera = picamera.PiCamera()

state_current = 0
state_previous = 0

def get_attachment(file):
fp = open(file, 'rb')
attachment = MIMEApplication(
fp.read(),
Name=basename(file)
)
attachment['Content-Disposition'] = 'attachment; filename="{basename}"' . format(basename=basename(file))
fp.close()
return attachment

def sendmail(files):
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = addr_from
msg['To'] = addr_to
msg.preamble = subject
for file in files:
msg.attach(get_attachment(file))
try:
s = smtplib.SMTP(smtp_host, smtp_port)
s.ehlo()
s.starttls()
s.ehlo()
s.login(user = smtp_user, password = smtp_pass)
#s.send_message(msg)
s.sendmail(addr_from, addr_to, msg.as_string())
s.quit()
except smtplib.SMTPException as error:
print "{date}: Error: unable to send email : {err}" . format(date=datetime.datetime.now(), err=error)

def capture():
print "{date}: Bewegung erkannt! Nehme Foto auf..." . format(date=datetime.datetime.now())
files = []
for i, filename in enumerate(camera.capture_continuous(STORAGE_LOCATION + 'image_{timestamp:%H-%M-%S-%f}_{counter:03d}.jpg')):
print "{date}: {cycle}. Foto aufgenommen..." . format(date=datetime.datetime.now(), cycle=i + 1)
files.append(filename)
if i + 1 == CAPTURE_COUNT:
break;
time.sleep(TIMEOUT_BETWEEN_CAPTURE)
if(SEND_EMAIL):
print "{date}: Fertig! Sende Mail..." . format(date=datetime.datetime.now())
sendmail(files)

print "Bewegungsmelder (CTRL-C zum Beenden)"
print "========================================="

try:
print "{date}: Sensor initialisieren ..." . format(date=datetime.datetime.now())
# Warten bis Sensor sich meldet
while GPIO.input(GPIO_PIR)==1:
state_current = 0
print "{date}: Fertig! Warte auf Bewegung..." . format(date=datetime.datetime.now())
# Schleife bis CTRL+C
while True :
# Status von Sensor auslesen
state_current = GPIO.input(GPIO_PIR)

if state_current==1 and state_previous==0:
capture()
state_previous=1
time.sleep(TIMEOUT_AFTER_CAPTURE)
print "{date}: Fertig! Warte auf Bewegung..." . format(date=datetime.datetime.now())
elif state_current==0 and state_previous==1:
state_previous=0

time.sleep(0.01)
except KeyboardInterrupt:
print "{date}: Exit" . format(date=datetime.datetime.now())
GPIO.cleanup()
Zuerst das Wichtigste ab Zeile 37. Gmail bietet nebenbei an, eine doppelte Sicherheitsabfrage einzurichten, die keine Mails über dieses Skript versenden lässt. Man muss sie entweder deaktivieren oder bevorzugt eine andere Mail-Adresse verwenden.

# Soll eine Mail gesendet werden?

SEND_EMAIL = 1

Mögliche Werte sind 0 (Nein) oder 1 (Ja)

# SMTP Einstellungen definieren

smtp_host = 'smtp.server.de'

beispielsweise 'smtp.gmail.com'

'smtp_port = 587

Meist 587 oder 465

smtp_user = 'username'

Kundennummer oder Mail-Adresse

smtp_pass = 'password'

Das Passwort, das Sie hoffentlich irgendwo notiert haben

# Absender und Empfänger für Mail definieren

subject = 'Bewegungsmelder ausgelöst'

addr_from = 'from@mail.de'

Sender (siehe oben)

addr_to = 'to@mail.de'

Empfänger, kann identisch mit dem Absender sein

 

Weitere Variablen sind:

GPIO_PIR = 7

# GPIO als "Input" definieren

Kann auch jeder andere freie GPIO sein, an dem der Bewegungsmelder hängt

# Speicherort definieren

STORAGE_LOCATION = '/home/pi/Desktop/'

Kann jedes Verzeichnis sein, das man auf dem Raspberry Pi selbst anlegt

# Timeouts definieren

TIMEOUT_AFTER_CAPTURE = 10

TIMEOUT_BETWEEN_CAPTURE = 1

# Anzahl der Bilder die durch eine Bewegung aufgezeichnet werden

CAPTURE_COUNT = 5

Voreingestellt: Die Kamera schießt fünf Bilder im Abstand von einer Sekunde. Dann wartet sie zehn Sekunden, bis sie wieder auf eine Bewegung reagiert.