Garagentor-Überwachung und -steuerung

Garagentor-Überwachung und -steuerung

Hat man einmal einen Raspberry Pi in seiner Garage installiert, gibt es viele Möglichkeiten ihn zu nutzen. Mein Wunsch ist, dass mein Garagentor und die Garagentüre nachts geschlossen sind. Das ist aber mit Kindern nicht immer so einfach. Ein Überwachung mit einem Smarthome könnte helfen. Wie das geht, erfahren Sie hier.

Es gibt heute mehrere sehr gute freie Smarthome Umgebungen, die eine solche Funktion einfach einbinden können (z. B. FHEM http://fhem.de/fhem_DE.html oder OpenHAB https://www.openhab.org/). Warum also das selber entwickeln?

Ich bin der Meinung, dass gerade der Bereich Smarthome super dafür geeignet ist, Interessierte an die Bereiche Digitalisierung, IoT und Programmierung heranzuführen. Mit den vielfältigen Möglichkeiten auf diesem Gebiet lassen sich eigene Vorstellungen heute mit einem überschaubaren technischen Aufwand realisieren.

Man erhält so auf spielerische Weise einen Einblick in die Funktionsweise des IoT:

Was ist alles notwendig, um auf dem Smartphone eine Webseite mit Informationen zur aktuellen Temperatur im Wohnzimmer anzuzeigen?

Und welche Technik dahinter steht: vom Webserver mit HTML- und PHP-Seiten bis zum Raspberry Pi mit Python-Software und angeschlossenen Elektronikbauteilen.

Und genau das möchte ich mit diesem Artikel tun:
Ein wenig Lust wecken eigene Ideen anzupacken und selber umzusetzen.

Weboberfläche
Weboberfläche

 

Funktionsweise

In unserer Garage befindet sich ein Tor mit Antrieb und eine Zugangstüre. Um diese beiden Elemente soll es gehen.

Die Anforderungen:

  • Das Garagentor soll sich per Smartphone öffnen lassen (nicht schließen)
  • Garagentor und -türe sollen über die Nacht geschlossen sein
  • Jeden Abend (20 Uhr) prüfen, ob das Garagentor oder die Garagentüre noch offen sind. Sind sie offen, eine E-Mail mit einem Hinweis verschicken.
  • Der aktuelle Zustand von Garagentor und -türe bereitstellen für alle Intranet-Geräte (Smartphone, Tablet, PC)
Prinzipaufbau
Prinzipaufbau Garagentor, Torantrieb und Zugangstüre

Systemaufbau

Um alle Anforderung umzusetzen, braucht man einige Bausteine. Die Basis bildet ein Raspberry Pi. Auf ihm laufen die Informationen zusammen und es werden von dort aus alle notwendigen Aktionen ausgelöst.

Die Visualisierung zum Benutzer hin erfolgt durch eine Webseite. Ein Apache Webserver erzeugt mit PHP-Unterstützung die Webseite.

Neben dem Webserver läuft auf dem Raspberry auch ein Skript, um die Kontakt-GPIO’s von Garagentor und -türe zu überwachen und entsprechende Ereignisse auszulösen.

Die Kommunikation erfolgt nur über Smartphone, Notebook, Tablet oder PC mit dem Webserver auf dem Raspberry Pi.

Systemaufbau
Systemaufbau mit Raspberry Pi als zentraler Komponente

 

Hardware

Reed-Kontakte

Das Garagentor wird in seiner Geschlossen-Position mit einem Kontakt überwacht. Genauso erfolgt das auch mit der Garagentüre.

Dafür eigenen sich am besten Reed-Kontakte. Sie werden im Handel in einer direkt verbaubaren Ausführung auch als Fensterkontakte bezeichnet (ebay Suche mit Fensterkontakt oder Türkontakt). Die Reed-Kontakte werden genauso wie Taster oder Schalter mit einem GPIO-Pin verbunden. Aufgrund meiner Leitungslängen (>10 m) verwende ich zusätzlich parallel einen Kondensator zur Vermeidung von Störsignalen.

Verdrahtung des Türkontakts
Verdrahtung des Türkontakts

Der Türkontakt wird am besten so montiert, dass die beiden Elemente im geschlossen Zustand nebeneinander liegen. Die meisten Türkontakte haben dafür Bohrungen für Schrauben im Gehäuse. Aber auch mit ein wenig Heißkleber funktioniert eine sichere Befestigung sehr gut. Löten Sie die Anschlussleitungen, empfiehlt sich ein Schrumpschlauch.

Montage des Türkontakts am Torrahmen
Montage des Türkontakts am Torrahmen

Relais-Karte

Für die Funktion zum Öffnen des Garagentors brauchen wir ein anderes Element. Die meisten Garagentore haben zum externen Öffnen einen eigenen Hardware-Kontakt, welcher geschlossen werden muss, um das Tor im Wechsel zu öffnen oder zu schließen (Taster-Funktion).

Dafür eignet sich am besten eine Relais-Karte. Diese gibt es fertig für den Raspberry Pi zu kaufen (z. B. als 2-fach-Relais-Karte).

2-Relais-Karte
Beispiel für eine 2-Relais-Karte

Die Relais-Karte benötigt als Anschlüsse VCC mit 5V, GND und einen GPIO-Pin als Signal. Ich verwende aus Sicherheitsgründen beide Relais. Ich möchte nicht, dass die Garage selbständig durch einen Fehler oder Reboot geöffnet oder geschlossen wird. Deshalb sind die beiden Ausgänge der Relais in Reihe geschaltet. Nur wenn beide geschlossen sind, erfolgt ein Signal an den Garagenöffner.

Ich möchte aus Sicherheitsgründen, mit dieser Lösung, das Tor nur öffnen können. Das kommt bei mir vor, wenn ich vor dem Garagentor stehe und keinen Funköffner dabeihabe – aber mein Smartphone.

Die Ausgangsseite der Relais-Karte wird mit dem externen Kontakt des Garagentorantriebs verbunden.

Damit ist die Hardware festgelegt und bereit. Im nächsten Schritt starten wir mit der Auswertung und Ansteuerung.

Wenn Sie mehr über Relaiskarten erfahren möchten, finden Sie eine gute Anleitung unter tutorials-raspberrypi.de.

GPIO-Überwachung und Ereignisse

Die Überwachung der GPIO’s erfolgt über ein Python-Programm, dass permanent im Hintergrund auf dem Raspberry Pi läuft. Um es beim Systemstart einzubinden, gibt es viele Möglichkeiten. Ich verwende hier die Variante über die Datei /etc/rc.local.

Öffnen Sie die Datei z. B. mit leafpad:

sudo leafpad /etc/rc.local

Und fügen am Ende vor der Zeile exit 0 folgendes ein.

su pi -c „python /home/pi/smarthome/gpio_events.py &”

Die Software deckt folgende Funktionen ab:

  • Erkennen, ob ein Reed-Kontakt geschlossen wurde
  • Prüfung, ob eine bestimmte Uhrzeit (20 Uhr) verstrichen ist, um eine Mail zu versenden
  • Status-Informationen speichern, um diese mit dem Webserver anzeigen zu können

Die beiden Reed-Kontakte werden über Events überwacht und mit Callback-Prozeduren ausgewertet.

for t in Taster:
    GPIO.setup(t.PinInput, GPIO.IN)
    GPIO.add_event_detect(t.PinInput,GPIO.BOTH,bouncetime=2000)
    GPIO.add_event_callback(t.PinInput,t.Event)

Wird ein Kontakt ausgelöst, schreibt die Callback-Prozedur die aktuelle Uhrzeit und Status in zwei Textdateien.

  • Die erste Datei speichert täglich alle Ereignisse. Neue Ergebnisse werden unten angehängt
  • Die zweite Datei enthält nur den letzten Eintrag
def Event(self,p1):
        global pathDocuments

        #Datei erweitern
        #append file
        tex=open(pathDocuments+'pin'+str(self.PinInput)+'/'+self.Filename+'_'+time.strftime('%d.%m.%Y')+'.txt','a')
        tex.write('\n'+time.strftime('%d.%m.%Y %H:%M:%S')+': '+str(GPIO.input(self.PinInput)))
        tex.close()

        #Datei mit Zeitstempel erzeugen
        #file with only a timestamp
        tex=open(pathDocuments+'pin'+str(self.PinInput)+'/status.txt','w')
        tex.write(time.strftime('%d.%m.%Y %H:%M:%S')+'\n')
        h=GPIO.input(self.PinInput)
        tex.write(str(h)+'\n')
        if (h==1):
            tex.write(self.StateStrHigh+'\n')
            print("Input "+self.Name+": Ereignis erkannt: "+self.StateStrHigh)
        else:
            tex.write(self.StateStrLow+'\n')    
            print("Input "+self.Name+": Ereignis erkannt: "+self.StateStrLow)
        tex.close()

Die beiden Dateien dienen dem Webserver dazu, einen Status anzuzeigen. Einmal als Übersichtsliste, das andere Mal als aktuellen Zustand.

Garagentor öffnen

Das Python-Programm für das Öffnen des Garagentors wird über ein PHP-Skript auf dem Webserver aufgerufen, dazu aber später mehr. Das Programm prüft zuerst, ob das Tor bereits geschlossen ist, nur dann erfolgen die weiteren Schritte. Denn sonst würde es durch die Taster-Funktion des Garagentorantriebs wieder geöffnet werden!

from time import *
import RPi.GPIO as GPIO

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

# verwendete Pins am Raspberry Pi
PinRelay1=23
PinRelay2=24
PinDoorClosed=14

# Ausgänge definieren
GPIO.setup(PinRelay1,GPIO.OUT)
GPIO.setup(PinRelay2,GPIO.OUT)

# Eingänge definieren
GPIO.setup(PinDoorClosed,GPIO.IN)

#Nochmalige Sicherheitsüberprüfung, ob Garagentor geschlossen ist
print("TOR ÖFFNEN:")

if GPIO.input(PinDoorClosed)==0: 
    print("    Tor wird geöffnet...")
    GPIO.output(PinRelay1,True)
    GPIO.output(PinRelay2,True)
    sleep(1)
    GPIO.output(PinRelay1,False)
    GPIO.output(PinRelay2,False)
    sleep(4)
    
    #Prüfen, ob Tor auf ist
    if GPIO.input(PinDoorClosed)==0:
        print("    Tor ist offen.")
    else:
        print("    Fehler. Tor ist zu!")
else:
    print("    Tor ist schon auf!")
       
GPIO.cleanup()

 

Webserver und PHP

Wie man einen Webserver und PHP für den Raspberry einrichtet, können Sie in verschiedenen anderen Blogs nachlesen. Mir haben am meisten die Erklärungen im Buch Raspberry Pi – Das umfassende Handbuch1) geholfen.

Die Daten, welche durch das obige Python-Programm erstellt werden, möchte ich im /var/www Ordner unter mydata speichern. Damit der Benutzer pi und der Webserver unter  www-data Zugriff haben, sind folgende Zeilen notwendig.

sudo mkdir /var/www/mydata
sudo chown pi.www-data /var/www/mydata
sudo chmod 2750 /var/www/mydata

Da www-data auch auf GPIO-Zugriff benötigt, um beispielsweise das Garagentor zu öffnen, muss er auch in die Gruppe gpio aufgenommen werden.

sudo adduser www-data gpio

Die Webseite selber wird mit PHP erweitert. Es gibt einen informativen und einen aktiven Teil.

Status der Tore anzeigen

Um den Status der Tore anzuzeigen, wird die oben beschriebene zweite Datei benutzt. In dieser ist der letzte Zustand des Tors gespeichert.

Aufbau der Datei: pin.txt

  1. Datum und Uhrzeit der letzten Zustandsänderung im Format JJJJ.MM.TT SS.MM.ss
  2. Wert des GPIO-Pins (0 oder 1)
  3. Name des Zustands im Klartext, z. B: GESCHLOSSEN

Beispiel:

14.10.2018 16:30:22
0
geschlossen

In PHP wird diese Datei eingelesen und entsprechend ausgewertet. Das passiert bei mir über eine eigene Funktion ImgPinStatus.

PHP-Funktion zum Auslesen einer Status-Textdatei:

gt_funktionen_imgpinstatus
funktionen.php: ImgPinStatus

Mit einer weiteren Funktion wird ein Button zum Öffnen des Garagentors auf der Webseite eingeblendet oder falls das Tor bereits offen ist auch nicht.

gt_funktionen_opendoorbutton
funktionen.php: OpenDoorButton

Aufgerufen werden die beiden Funktionen auf der Hauptseite index.php. Dort finden Sie auch den vollständigen Code.

Tor öffnen

Das Öffnen des Tors erfolgt mit dem oben vorgestellten Python-Programm. Dieses wird nach Anklicken des Links aufgerufen. Falls das Tor geschlossen ist, wird es geöffnet.

Danach wird über den Befehl header(‘Location: ‘.($_SERVER[‘PHP_SELF’])) wieder die Hauptseite geöffnet. Der Befehl ist extrem wichtig für den gesamten Ablauf. Wird er nicht eingebaut, könnte durch ein Aktualisieren des Browers nochmal ein Signal gesendet werden.

Button "Tor öffnen"
Button “Tor öffnen”

Mails versenden

Was jetzt noch fehlt ist die regelmäßige abendliche Prüfung, ob auch wirklich Garagentor und -türe für die Nacht geschlossen sind. Um dieses Thema geht es in diesem Abschnitt.

Wie man mit Python eine Mail versendet, habe ich schon im Artikel Kaninchen, Taster und Lean-Management beschrieben.

Die Uhrzeit der Prüfung wird im Objekt myInput über die Eigenschaft TestInterval eingestellt. Für eine tägliche Prüfung um 20 Uhr ist dieser Eintrag der Richtige:

#Nummer des Wochentags eintragen oder * für täglich
#Enter number for weekday for weekly or * for daily
#0: Sonntag / Sunday
#1: Montag / Monday
#...
#6: Samstag / Saturday

myInput[0].TestInterval="*-20:00"

In der Hauptroutine der Python-Datei gpio_events.py wird überprüft, ob TestInterval bereits verstrichen ist.

Ob das Ereignis heute schon eingetreten ist, wird über die Variable TestDone zwischengespeichert.

Jeden Tag um 23:59 Uhr werden dann alle Zähler zurückgestellt für den nächsten Tag.

print("Warte auf Signale...")
#print("Wait for signals...")
tick=0
signal0h="-"
try:
    while True:                 
        time.sleep(0.2)
        tick=tick+1
        if tick>300: 
            #Jede Minute prüfen: sind Erinnerungen notwendig?
            #Check every minute: are reminders necessary?
            tick=0
            s=time.strftime("%Y.%m.%d")
            #Zähler nach 23:59 zurücksetzen
            #reset the counter at 23:59
            if s!=signal0h:
                if time.strftime("%H:%M")=="23:59":
                    signal0h=s
                    for t in myInput:
                        if t.TestInterval!="-":
                            if t.TestInterval[0]=="*":
                                #wenn tägliches Intervall, dann zurücksetzen
                                #if daily interval, then reset
                                t.State=False
                                t.TestDone="-"
                                print("Tägliches Zurücksetzen: "+t.Name)
                                #print("Daily reset: "+t.Name)
                            else:
                                #wenn wöchentlich, dann prüfen ob der Tag stimmt
                                #if weekly, then check if day fits
                                if time.strftime("%w")==t.TestInterval[0]:
                                    t.State=False
                                    t.TestDone="-"
                                    print("Tägliches Zurücksetzen: "+t.Name)
                                    #print("Daily reset: "+t.Name)
                                 
            #Prüfen, ob Erinnerungen notwendig sind?   
            #Check if reminder is necessary?
            for t in myInput:
                if t.TestInterval!="-":
                    if s!=t.TestDone:
                        if ((t.TestInterval[0]=="*") and (time.strftime("%H:%M")==t.TestInterval[2:])) or (time.strftime("%w-%H:%M")==t.TestInterval):
                            #Es ist die erste Prüfung
                            #it is the first time of the check
                            t.TestDone="X"
                            #dann sind keine weiteren Prüfungen erforderlich   
                            #because of this, there's no further check
                            if t.State==False:
                                MailVersenden('Thomas Angielsky <yourname@yourserver.com>','Hinweis',t.Message)
                                print(t.Message)

Webseite

Bei der Umsetzung als Webseite gibt es fast keine Grenzen. Für die Seitengestaltung verwende ich HTML und CSS.

index.php
Beispiel für die Webseite index.php

Die Formatierungen in der index.php werden mit den CSS-Definitionen aus der Datei styles.css erstellt.

Das Stylesheet selbst ist ziemlich groß. Sie finden es im html-Ordner des Projekts im Download-Link.

CSS ist ein interessantes Thema. Falls Sie sich dafür interessieren und Lust haben tiefer einzusteigen, hat mir das Buch von Peter Müller 2) viel Spaß bereitet. Vielleicht ist es auch ein guter Ansatzpunkt für Sie.

Testen, Testen, Testen

Bevor das Ganze direkt in die Garage eingebaut wird, sollten Sie es ausgiebig testen. Dafür bietet sich ein kleiner Testaufbau an. So können Sie gut alle möglichen Situationen vorher ausprobieren.

Testaufbau
Testaufbau

 

Probleme und Erweiterungen

Damit hat man schon ein recht komfortables und ausbaubares System beisammen. Möchte man einen noch klareren Zustand, überwacht man am besten auch die Offen-Position, zumindest des Garagentors.

Je mehr Funktionen dazu kommen, desto aufwändiger werden auch die Realisierung und die Wartung.

Ich hoffe Sie haben jetzt auch einen besseren Einblick, was alles für eine handvoll Smarthome-Funktionen zu tun ist. Und können so besser einschätzen, was alles in professionellen Smarthome-Systeme abläuft.

Mir gefällt auf jeden Fall die Möglichkeit, alle Funktionen und Visualisierungen selber gestalten zu können und genau zu wissen, was wie und warum passiert.

Viel Spaß beim Nachbauen und Experimentieren.

Download

symbol_download

  Python-Programm und HTML/PHP-Dateien für den Webserver

Links

Wikipedia-Artikel zu Reedschaltern
https://de.wikipedia.org/wiki/Reedschalter

1) Raspberry Pi – Das umfassende Handbuch“ von Michael Kofler, Charly Kühnast, Christoph Scherbeck (Rheinwerk)

https://www.rheinwerk-verlag.de/raspberry-pi_4466/?gclid=Cj0KCQjwkd3VBRDzARIsAAdGzMBsBKZND8GvXuvxtdcKGGl9dWTHj4CGSSxNUxwzCao0ahsaO4tE1VYaAmWTEALw_wcB

2) Einstieg in CSS von Peter Müller (Rheinwerk)

https://pmueller.de/buecher/einstieg-in-css-2015-updates/

Dieser Beitrag hat einen Kommentar

Kommentar verfassen

Menü schließen