Wassersensor mit Snapshot und Mailversand mit Bild im Anhang

L I V E Stammtisch ab 20:30 Uhr im Chat
  • [font="Calibri"]Hallo zusammen,[/font]

    [font="Calibri"]hab mir gedacht, doppelt hält besser und möchte einen Wassersensor bauen, der nicht nur eine Alarmmeldung als Mail abgibt, sondern auch gleich ein Foto mitschickt.[/font]

    [font="Calibri"]Ohne Kamera- und Attachmentbefehle für das jeweilige Bild im Skript funktioniert es problemlos.[/font]

    [font="Calibri"]Anforderungen an das Skript:[/font]
    [font="Calibri"]Wassersensor liegt auf PIN18.[/font]
    [font="Calibri"]Bei Nässe soll ein Foto über die Raspi Cam gemacht und mit einer Mail als Anhang verschickt werden.[/font]
    [font="Calibri"]Wenn der Sensor wieder trocken ist, dann erneut Foto machen und eine Mail mit Anhang verschicken.[/font]
    [font="Calibri"]Aktueller Fehler beim Testen:[/font]
    [font="Calibri"]In Zeile 114 [/font]
    [font="Calibri"]return 0[/font]
    [font="Calibri"]SyntaxError: 'return' outside function[/font]
    [font="Calibri"] [/font]
    [font="Calibri"]Wo liegt denn hier das Problem? Der Zähler müsste doch den Wert problemlos ausgeben können?[/font]
    [font="Calibri"]Hoffe, jemand hat hier einen Tip.[/font]


    [font="Calibri"]

    Python
    #!/usr/bin/python[/font][/size][/color]import smtplibimport RPi.GPIO as GPIOimport stringimport timeimport picamerafrom datetime import datetimefrom email.mime.text import MIMETextfrom email.mime.image import MIMEImagefrom email.mime.multipart import MIMEMultipart# MAIL ##############################################username = "Mailpassword = "xxxxxxxxxx"From = "Absender"To =  "Empf"# Conditions ########################################water_count = 0Subject_wet = "Wassersensor ist nass"Body_wet = "NASS"Subject_dry = "Wassersensor ist trocken"Body_dry = "TROCKEN"#ENTWEDER "wet" oder "dry" als Bedingungdef email(condition):   print "Attempting to send email"   if condition == "wet":# Bild NASS ##########################       with picamera.PiCamera() as camera:          camera.resolution = (1024, 768)          camera.start_preview()  # Camera warm-up time          time.sleep(2)          camera.capture("nass.jpg")f_time = datetime.now().strftime("%a %d %b @ %H:%M")msg = MIMEMultipart()msg.attach(MIMEText(file("/home/pi/nass.jpg").read()))Body = string.join((       "From: %s" % From,       "To: %s" % To,       "Subject: %s" % Subject_wet % f_time,       "",       Body_wet,       ), "\r\n")if condition == "dry":# Bild TROCKEN #######################   with picamera.PiCamera() as camera:       camera.resolution = (1024, 768)       camera.start_preview()  # Camera warm-up timetime.sleep(2)camera.capture("trocken.jpg")f_time = datetime.now().strftime("%a %d %b @ %H:%M")msg = MIMEMultipart()msg.attach(MIMEText(file("/home/pi/trocken.jpg").read()))       Body = string.join((           "From: %s" % From,           "To: %s" % To,           "Subject: %s" % Subject_dry % f_time,           "",           Body_dry,           ), "\r\n")   # Mail Versand mit Bild als Anhang ######################server = smtplib.SMTP("smtpSERVER:587")server.starttls()print "Logging in..."server.login(username,password)print "Logged in as "+username+"."server.sendmail(From, [To], Body, msg.as_string())server.quit()print "Email wurde gesendet."# Test auf Wasser ########################################## 0 for trocken# 1 for nass# Sensor liegt auf Pin 18 def RCtime (RCpin):   reading = 0   GPIO.setmode(GPIO.BCM)   GPIO.setup(RCpin, GPIO.OUT)   GPIO.output(RCpin, GPIO.LOW)time.sleep(1) GPIO.setup(RCpin, GPIO.IN)   # loop 1 mswhile True:       if (GPIO.input(RCpin) == GPIO.LOW):           reading += 1       if reading >= 1000:           return 0       if (GPIO.input(RCpin) != GPIO.LOW):           return 1print "In Bereitschaft..."while True:   time.sleep(1)# loop if longer wet #######################   water_count = 0   if RCtime(18) == 1:       print "Sensor ist nass"# Mailversand erneut, wenn immer noch nass ("wet") #######       while True:           time.sleep(1)           if RCtime(18) == 1:               print "Sensor ist immer noch nass."if water_count == 5:           email("wet")               water_count = water_count + 1                 continue           if RCtime(18) == 0:               print "Sensor ist wieder trocken"# Mailversand, wenn trocken ("dry")               email("dry")               print "Wassersensor wieder in Bereitschaft"[color=#000000][size=14][font="Calibri"]               break

    Thx im Vorhinein.[/font][/size][/color]
    Automatisch zusammengefügt:
    ACHTUNG - bitte beachten!
    Im Code sind am Anfang und Ende komischerweise Steuerzeichen für die Farbe drin - die gehören natürlich nicht zu meinem Code. Keine Ahnung, wie die reingekommen sind.

    Einmal editiert, zuletzt von Raspiuser8716 (28. Juli 2017 um 15:47)

  • Wassersensor mit Snapshot und Mailversand mit Bild im Anhang? Schau mal ob du hier fündig wirst!

  • Hallo,

    das Problem steht doch schon exakt in der Fehlermeldung beschrieben: du verwendest `return` außerhalb einer Funktion. Das ist in Python halt syntaktisch falsch, ergo gibt's 'ne Fehlermeldung. Wobei mir bei deinem Quelltext wie gepostet nicht klar ist, ob du `return` wirklich falsch verwenden willst oder ob nur deine Einrückungen nicht stimmen...

    Gruß, noisefloor

  • [font="Arial"]Hallo noisefloor,[/font]

    [font="Arial"]die Funktion ist[/font]

    [font="Courier New"]def RCtime (RCpin):
    reading = 0[/font]

    wieso erkennt der Interpreter nicht den Zusammenhang zwischen der Funktion und der bedingten Anweisung?

    Zitat

    Wobei mir bei deinem Quelltext wie gepostet nicht klar ist, ob du `return` wirklich falsch verwenden willst oder ob nur deine Einrückungen nicht stimmen...

    Meinst Du damit, dass für den Interpreter return 0 auf selber Höhe stehen muss wie reading = 0, damit er den Zusammenhang zwischen Funktion und dem 2. Teil erkennt?

    Thx für deine Hilfe.

  • Hallo,

    Einrückungen sind in Python _EXTREM_ wichtig, weil damit zusammengehörende Blöcke "markiert" werden.

    Gem. Quelltext in deinem 1. Posting gehört die Zeile `time.sleep(1)` und alles was danach kommt _nicht_ mehr zur Funktion `RCtime()`, weil `time.sleep(1)` die gleiche Einrückungstiefe wie `def RCtime(RCpin)` hat, womit die Zeile nicht mehr zur Funktion gehört. Und damit das `return` später auch nicht.

    In Bezug auf Einrückungen solltest du wohl dringend das Python-Tutorial o.ä. lesen, weil, wie gesagt, essentiell wichtig. Ohne das verinnerlicht zu haben kannst du nicht in Python programmieren. Noch nicht mal schlecht ;)

    Gruß, noisefloor

  • Hallo noisefloor,

    danke für den Hinweis - war dringend notwendig ;-), habe die restlichen Einrückungsfehler ausgebessert, jetzt kommt aber:

    "Subject: %s" % Subject_wet & f_time,

    Type Error: not all arguments converted during string formatting

    Welcher Teil kann hier nicht umgewandelt werden?

    Thx

  • Hallo,

    Code
    "Subject: %s" % Subject_wet % f_time


    ist kein gültiges Python - da sind zwei Fehler drin. Wenn du zwei oder mehr Werte in den String übergeben willst, dann musst du die Werte in ein Tupel stecken, 2x %foo ist nicht zulässig. Außerdem erwartet dein String `Subject: %s` nur einen Wert. Generell möchtest du vielleicht du neuere Format-Methode von Strings nutzen, die funktioniert auch bei Python 2.7.

    Gruß, noisefloor

  • Hallo noisefloor,

    hab jetzt alle möglichen Varianten ausprobiert und entweder kommt ein Einrückungsfehler oder die Meldung bei return - kein Bezug zu einer Funktion.
    Wo liegt denn hier der Hase im Pfeffer?

    Hoffe, Du hast einen Tip.

    Thx

    ACHTUNG, wenn ich einen Code reinkopiere, dann schneidet der Editor teilweise eine Einrückung am Anfang ab - Du kannst davon ausgehen, dass alle Einrückungen von mir im Originalcode Vielfache von 4 sind.

  • Hallo,

    Zitat

    hab jetzt alle möglichen Varianten ausprobiert


    Programmieren ist nicht raten...

    Zitat

    ACHTUNG, wenn ich einen Code reinkopiere, dann schneidet der Editor teilweise eine Einrückung am Anfang ab - Du kannst davon ausgehen, dass alle Einrückungen von mir im Originalcode Vielfache von 4 sind.


    Ersteres sollte nicht passieren, letzteres hilft als Aussage wenig, weil dein Fehler in den Einrückungen genau hier das Problem ist.

    Am besten verwendet _nur_ Whitespaces (=Leerzeichen) zur Einrückung, auf keinen Fall Tabs und Leerzeichen mischen. Das gibt in der Regel Probleme.

    Grundsätzlich muss ein `return` _immer_ gegenüber dem `def ...` eingerückt sein. Sonst gibt es einen Fehler.

    Gruß, noisefloor

  • Hallo noisefloor,

    nein, ich rate nicht, sondern habe gemäß den Regeln die Einrückungen gemacht und trotzdem die Fehlermeldungen bekommen. Mir ist klar, dass etwas nicht stimmt ;-), nur war ich verblüfft, als ich alle Einrückungen für Python so gemacht hatte, dass kein diesbezüglicher indent Fehler mehr aufgetreten ist. Dann kam eben die Meldung, dass return mit keiner Funktion verknüpft ist.
    Ja und dann habe ich in 4er Schritteinheiten das return nach rechts und links verschoben - mit dem bekannten Ergebnis.

    Werde die While Teile mal rausnehmen und schauen, ob es dann funzt.

    Aber zur Sicherheit die Frage: Wie kopierst Du einen Code aus dem Skript in den Editor vom Forum? Ich habe die Datei mit dem Texteditor geöffnet, den entsprechenden Teil kopiert und im IE mit dem "Einfügen" Schaltknopf unter dem kleinen Fenster den Code übernommen. Im Originalskript sind alle Einrückungen korrekt.

    Thx an Dich.

  • Hallo,

    das Return Problem ist nun erledigt. Jetzt hakt es im Haupteil des Skripts. Habe die Kamera Teile rausgenommen und nur das Wassermelder Skript übrig lassen. Erst wenn das funzt, werde ich den Rest Schritt für Schritt einbauen.

    Es kommt nun erneut ein Einrückungsfehler. Habe alle Einrückungen peinlich genau auf Vollständigkeit und TABs überprüft. Jetzt kann nur ich einen Denkfehler haben.
    Der Fehler ist im Hauptteil ganz unten. Zeile 94 Meldung: Einrückung passt nicht und keine Verbindung zu einer Funktion.
    Meine Logik für die Einrückungen - hier nur zur Beschreibung ohne richtige Abstände - die sind im angehängten Skript akurat:

    while True:
    time.sleep(1)
    water_count = 0
    if RCtime(18) == 1: ALS UNTERFUNKTION VON WHILE TRUE - 4 Einheiten rein
    print "Sensor ist nass"
    while True: ALS UNTERFUNKTION VON if RCtime(18) == 1 - 8 Einheiten rein
    time.sleep(1)
    if RCtime(18) == 1: ALS UNTERFUNKTION VON WHILE TRUE der if RCtime- 12 Einheiten rein
    print "Sensor ist immer noch nass..."
    if water_count == 5: ALS UNTERFUNKTION der RCtime(18) aus Zeile 83 - 8 Einheiten rein
    email("wet")
    water_count = water_count + 1
    continue
    if RCtime(18) == 0: ALS UNTERFUNKTION VON WHILE TRUE aus Zeile 86 - 12 Einheiten rein
    print "Sensor ist trocken"
    email("dry")
    print "Wasserwaechter aktiv..."
    break


    Hoffe, jemand sieht hier den Knoten.

    Thx
    Automatisch zusammengefügt:
    Das Skript noch:

  • Hallo zusammen,

    hab jetzt das Script umgemodelt.

    Aufruf mit Putty:

    Der Sensor funktioniert, das Script reagiert und meldet einen nassen Sensor, die LED an der Camera leuchtet und hat auch einmal ein Foto gemacht, doch dann kommt im Script eine Fehlermeldung. Die Mail mit dem Foto wird nicht versandt und das Script wird beendet

    Anzeige im Putty:

    Wasserwaechter aktiv...

    Sensor ist nass

    Sensor ist immer noch nass...

    Sensor ist immer noch nass...

    Sensor ist immer noch nass...

    Sensor ist immer noch nass...

    Sensor ist immer noch nass...

    Sensor ist immer noch nass...

    Attempting to send email

    Logging in...

    Traceback (most recent call last):

    File "water.py", line 158, in <module>

    email("wet")

    File "water.py", line 113, in email

    server.login(username,password)

    File "/usr/lib/python2.7/smtplib.py", line 622, in login

    raise SMTPAuthenticationError(code, resp)

    smtplib.SMTPAuthenticationError: (535, 'Incorrect authentication data')

    Der Username und das Passwort stimmen aber.

    Meine Fragen dazu:

    1)Was bedeutet die Traceback Meldung?

    2) Ich habe mit der Mailadresse, dem Passwort sowie dem SMTP Server sonst auch auf Port 587 gearbeitet - keine Probleme. Was bedeutet nun die Fehlermeldung und wie kann ich die beheben?

    Das Script ist im Anhang drin.

    Hoffe, dass jemand einen Tip hat. Thx schon mal.

  • Hallo Bootsmann,

    vielen Dank für den Tip.

    Es ist eine gmx Adresse und die hat problemlos mit anderen Scripts, die ähnlich aufgebaut sind sowie auch sendmail funktioniert.

    Schreibung der Anmeldedaten ist richtig, 587er Port geht sonst auch.

    Habe das server.ehlo_or_helo_if_needed() vor dem server.login(username,password) eingesetzt - bringt dieselbe Fehlermeldung.

    Einziger Unterschied ist im jetzigen Script, dass ein Anhang mitgeschickt werden soll. Kann das ein Problem sein. Wenn ja, wie lösen?

    Hoffentlich hast Du einen Tip.

    Thx schon mal.

  • Hallo zusammen,

    habe nun den SMTP Port auf 25 gesetzt - jetzt geht es, aber.......

    Test Sensor:

    Das Script läuft etwas seltsam: Fotos werden korrekt geschossen und verschickt.

    Wenn die Mail mit dem Schnappschuss gesendet werden soll, dann dauert dies ca. 30. Im Putty steht dann lange „logged in as….“ Aber das Script wird dann erst nach ca. 30 Sekunden weiter verarbeitet.

    Seltsam ist, dass 2 Mails mit einer „Nass“ Status Meldung hintereinander verschickt werden und dann – obwohl der Sensor noch nass ist, gleich 2 Mails mit der „Trocken“ Status Meldung kommen.

    Weiter seltsam, dass nach Trocknen des Sensors um 22:58 nochmals 2 Mails kommen mit der „Nass“ Status Meldung.

    Das Ziel sollte sein:

    Wenn der Sensor nass ist, nur eine Mail samt Foto und der Status Meldung „Nass“ schicken.

    Wenn der Sensor wieder trocken ist, nur eine Mail samt Foto und der Status Meldung „Trocken“ schicken.

    Hier der Ablauf chronologisch – Details im Screenshot vom Putty:

    22:40 Sensor wird benetzt

    22:41 Mail: Sensor ist nass

    22:41 Mail: Sensor ist nass

    22:42 Mail: Sensor ist trocken – obwohl die LED vom Wandler den Status nass anzeigt und im Putty weiterhin die Meldung „Sensor ist nass“ kommt.

    22:43 Mail: Sensor ist trocken – obwohl die LED vom Wandler den Status nass anzeigt und im Putty weiterhin die Meldung „Sensor ist nass“ kommt.

    Im Putty kommt periodisch die Meldung, dass der Sensor nass ist. Die LED vom Wandler zeigt nach wie vor den Zustand „nass“ an.

    22:56 Sensor wird getrocknet – Putty Meldung „Sensor ist trocken – Mail wir gesendet

    22:58 Mail: Sensor ist nass

    22:58 Mail: Sensor ist nass kommt nochmals

    22:59 Mail: Sensor ist trocken

    22:59 Mail: Sensor ist trocken kommt nochmals

    Hoffe, dass jemand hier die Ursache für die verkehrten Meldungen erkennen kann.

    Thx schon mal

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!