Raspberry Pi 3B als Wassermelder

Ausgangsproblem: Wie bekomme ich mit, dass in einem Keller, der keinen Abfluss hat, ein Wasserschaden vorliegt und der Keller mit Wasser vollläuft?

Bei einer kurzen Internetsuche fand ich eine schöne Seite: Raspberry Pi als Wassersensor benutzen – E-Mail als Benachrichtigung. Dort wird anhand des älteren Modells Raspi 2 mit detaillierten Skizzen und Programmen gezeigt, wie man den Raspi dazu bringt, Wasser zu detektieren und mit relativ kurzem Python-Code eine E-Mail zu versenden.

Eine E-Mail mit dem Raspi versenden

Tatsächlich gelingt das mit Python mit relativ wenigen Zeilen. Jedoch gibt es kleine, entscheidende Details, die man berücksichtigen muss. Vorab: Das Senden von Mails gelang mir nur mit gmail.com, bei den anderen Anbietern t-online.de und web.de ist es mir bisher nicht gelungen. Mit Hilfe der genannten Quellen habe ich folgendes Testprogramm melder_status.py für Python3 zusammengestellt:

# Autor: M. Sprau
# Datum: 25.10.2020
# Programm sendet die uptime-Zeit des Raspis.
# Eintrag in crontab kontrollieren.

import smtplib, shlex, subprocess

# uptime-Zeit des Raspis bestimmen
cmd = "uptime -p"
args = shlex.split(cmd)
p = subprocess.Popen(args, stdout=subprocess.PIPE)
output = p.communicate()

# Benutzerdaten z.B. bei gmail.com
user = 'BENUTZER'   # @gmail.com kann hier weggelassen werden
pwd = 'PASSWORT'

# Mail absenden
mail_text = str(output) + '\n ist der Raspi nun online!'
subject = 'Online-Status des Raspis'
MAIL_FROM = ''
RCPT_TO = 'EMFFÄNGER@ADRESSE'
DATA = 'From:%s\nTo:%s\nSubject:%s\n\n%s' % (MAIL_FROM, RCPT_TO, subject, mail_text)
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
#print ("Logging in ...")
server.login(user, pwd)
#print ("Begin sending ...")
server.sendmail(MAIL_FROM, RCPT_TO, DATA)
#print ("Logging out ...")
server.quit()

Wie im Quelltext zu sehen ist, wird das Passwort im Klartext abgespeichert. Daher sollte man sich aus Sicherheitsgründen ein separates gmail-Konto nur für diesen Zweck anlegen.

ACHTUNG: Die Methode wurde von Google ab Juni 2022 gesperrt! Bis dahin eingerichtete Konten funktionieren aber noch.

Nachdem nun die Benachrichtigung per e-mail funktioniert, möchte ich natürlich sicherstellen, dass der Raspi auch eingeschaltet ist, um einen potenziellen Wassereintritt zu melden. Dazu kann man sich per Eintragung im crontab reglemäßig eine mail zusenden lassen. Für meine Zwecke reicht es aus, zweimal wöchentlich eine Statusmail zu erhalten, die dann gleich die uptime-Zeit des Raspis mitsendet. Dazu kann Folgendes eingetragen werden, nachdem man im Terminal den Befehl crontab -e aufgerufen hat:


  # status senden: mittwochs, samstags 14.00 Uhr
  @reboot      python3 /home/pi/wasser_sensor.py
  0 14 * * 3,6 python3 /home/pi/melder_status.py

  #
  

Dabei ist wichtig, dass die letzte Zeile im crontab ein Kommentar oder eine Leerzeile ist. Mit der 2. Zeile wird beim Booten des Raspis das Pythonprogramm wasser_sensor.py gestartet, was im nächsten Abschnitt beschrieben wird.

Der Text einer Status-Mail von melder_status.py sieht z.B. so aus:

  (b'up 18 weeks, 1 day, 21 hours, 49 minutes\n', None)
  ist der Raspi nun online!

Wassersensor

Im Programm werden die GPIOs des Raspis benutzt, hier im Programm GPIO 18 und als zweiter Pin +3,3 V. Der Schutzwiderstand ist 100 Ohm, wobei auch Versuche mit 150 Ohm erfolgreich waren. Dazu werden zwei geeignete Steckkabel rausgeführt, wovon ein Kabel außen eine „Buchse“ hat. Der Widerstand wird entsprechend abgelängt. Damit er nicht zu leicht herausrutschen kann, wird am eingesteckten Drahtstück etwas Lötzinn aufgebracht. Schließlich werden die beiden Stecker mit einer Heißklebepistole verklebt.
Beim Programmstart wird zunächst eine E-Mail gesendet, damit man über den Beginn informiert wird. Im Hauptprogramm wird alle 10 s geprüft, ob der Sensor nass ist. Falls ja, wird dann alle 30 s erneut geprüft und eine entsprechende E-Mail versendet. Das benutzte Programm kann hier heruntergeladen werden: wasser_sensor.py.

#!/usr/bin/python3
# erweitert von M. Sprau
# 08.11.2020

# Nach einem Neustart wird zuerst eine mail gesendet.

import smtplib
from time import sleep

# warten nach Neustart, sonst kann die mail noch nicht abgesendet werden, weil die Dienste noch nicht verfügbar sind.
sleep(15)

# Benutzerdaten z.B. bei gmail.com
user = 'BENUTZER'   # @gmail.com kann hier weggelassen werden
pwd = 'PASSWORT'

subject = 'Neustart des Rapis'
mail_text ='''
Hallo,
der Raspi ist gerade neu gestartet. Wassersensor ist nun aktiv.
'''

MAIL_FROM = 'ABSENDER@ADRESSE'
RCPT_TO = 'ZIEL@ADRESSE'
DATA = 'From:%s\nTo:%s\nSubject:%s\n\n%s' % (MAIL_FROM, RCPT_TO, subject, mail_text)

server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
#print ("Logging in ...")
server.login(user, pwd)
#print ("Begin sending ...")
server.sendmail(MAIL_FROM, RCPT_TO, DATA)
#print ("Logging out ...")
server.quit()

#######################################
# Eigentliches Wasser-Sensor-Programm #
#######################################

#########
# About #
#########
# This script uses a Raspberry Pi to sense for the presense or absense of water.
# If there is water, an email is sent and a buzzer goes off.
# When it's dry again, another email is sent, and the buzzer turns off.

# To run this script at boot, edit /etc/rc.local to include (no quotes) 'sudo python .py'
# bzw.: crontab -e anpassen

###########
# License #
###########
# Released under the WTFPL.
#Full text and more information here: http://en.wikipedia.org/wiki/WTFPL

########################################
# Gmail login credentials to send email#
########################################
user = 'BENUTZER'   # @gmail.com kann hier weggelassen werden
pwd = 'PASSWORT'

############################
# General Email Parameters #
############################
MAIL_FROM = ""
RCPT_TO =  ['ZIEL@ADRESSE']  # max. nur 1 Adresse erlaubt, sonst Fehler im gmail-Konto!


#######################################
# Email Parameters when sensor is Wet #
#######################################
subject_wet = "Raspi Wasser-Sensor ist nass!"
body_wet = "Achtung,\n der Raspi hat einen Wasseraustritt im Keller gemeldet!\n Bitte kontrollieren!\n"

#######################################
# Email Parameters when semsor is Dry #
#######################################
subject_dry = "Raspi Wasser-Sensor ist trocken!"
body_dry = "Entwarnung, der Sensor ist trocken."

import RPi.GPIO as GPIO

# Function Definitions
#takes either "wet" or "dry" as the condition.
def email(condition):
    if condition == 'wet':
        DATA = 'From:%s\nTo:%s\nSubject:%s\n\n%s' % (MAIL_FROM, RCPT_TO, subject_wet, body_wet)

    if condition == 'dry':
        DATA = 'From:%s\nTo:%s\nSubject:%s\n\n%s' % (MAIL_FROM, RCPT_TO, subject_dry, body_dry)

    # The actual mail send
    server = smtplib.SMTP('smtp.gmail.com:587')
    server.starttls()
    server.login(user, pwd)
    server.sendmail(MAIL_FROM, RCPT_TO, DATA)
    server.quit()

# Tests whether water is present.
# returns 0 for dry
# returns 1 for wet
# tested to work on pin 18
def RCtime (RCpin):
    reading = 0
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(RCpin, GPIO.OUT)
    GPIO.output(RCpin, GPIO.LOW)
    sleep(1)
    GPIO.setup(RCpin, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)    # This takes about 1 millisecond per loop cycle
    while True:
        if (GPIO.input(RCpin) == GPIO.LOW):
            reading += 1
        if reading >= 1000:
            return 0
        if (GPIO.input(RCpin) != GPIO.LOW):
            return 1

# Main Loop
sleep(25) # damit mail aus melder_neustart.py fertig gesendet wurde.
print('Waiting for wetness...')
while True:
    sleep(10)
    if RCtime(18) == 1:
        print("Sensor is wet")
        email('wet')
        while True:
            sleep(30)
            if RCtime(18) == 1:
                print("Sensor is still wet...")
                email('wet')
                continue
            if RCtime(18) == 0:
                print("Sensor is dry again")
                email('dry')
                print("Waiting for wetness...")
                break

 

Falls eine Mail vom Raspberry Pi nicht abgesendet und blockiert wurde, muss man sich auf seinem Google-Account anmelden. Dort ggf. im Reiter Sicherheit kontrollieren und die App „Linux“, so wurde der Anmeldeversuch meines Raspis genannt, entsprechend freigeben.

Links

Ähnliche Beiträge