RPI getriggerte Fotos von RPI3 auf email

  • Hallo Experten,

    Habe das folgende Script für eine Heim-Überwachungsanlage mit einem RPI 3 geschrieben,

    das weitgehend funktioniert und in github abgelegt, und noch als .txt angehängt, es hat hier nicht Platz:

    https://gist.github.com/luemar…4607bae3395360016ab4c9e48.

    (konnte trotz allem Bemühen keine gleichmässige Zeilen-Einrückung erzielen).



    Mein (letztes) Problem:

    Jedes Mal wenn ein Foto nach PIR-Aktivierung gemacht wird bekomme ich im email die

    vorherigen Fotos mitgeschickt, also jedes Mal ein Foto mehr und die Nummerierung

    ist jedes Mal anders. Im Verzeichnis /home/pi finde ich dann jeweils den Namen des

    letztgemachten Fotos.


    Mit einem früheren Script mit RPi.GPIO war das nicht der Fall. Hat jemand ein Idee wo der

    Fehler liegt ?
    Luemar.

  • konnte trotz allem Bemühen keine gleichmässige Zeilen-Einrückung erzielen

    Das hat bei github aber dann auch nicht funktioniert :denker:. Du hängst bei jedem Durchlauf ein weiteres Bild per mime.attach an.


    Edit: Marcus, du solltest jetzt dringend dein Emailpasswort ändern. Ich hab den Anhang gelöscht (thx bootsmann), da er pw und co enthielt.

    Der Unterschied zwischen Genie und Wahnsinn definiert sich im Erfolg.

  • luemar

    Du muss dein Programm dringend in Funktionen aufteilen. Auf Modulebene haben nur Konstanten, Klassen und/oder Methoden/Funktionen zu stehen. Eine Funktion - eine Aufgabe


    zB:


    Eingerückt wird immer 4 Leerzeichen pro Ebene. Wie man Namen per Konvention richtig schreibt, steht hier.

  • Hallo,


    die Einrückungen sind auch wie bei github gezeigt kaputt - so kann ddas Skript niemals laufen. Und man kann als Außenstehender kaum beurteilen, wie was laufen soll.

    Könnte es sein, dass du Leerzeichen und Tabs mischst?


    Die Verwendung von `global` ist in 99,9% der Fälle nicht nötig und falsch. In deinem Skript ist es doppelt falsch, weil du so wie so nur eine Funktion hast und darum außerhalb den `count` gar nicht brauchts.


    Nackte try-except wie

    Code
    try:        
        smtp.sendmail(frm, to, mime.as_string())
    except:       
        print'Uebermittlungsfehler'

    sind ganz schlecht, weil damit _alle_ Fehler abgefangen werden, auch Programmierfehler. Das kann die Fehlersuche extrem erschweren.


    Strings formatiert man mit der `format`Methode von Strings, nicht durch zusammenstückeln mit Kommas getrennt.


    Gruß, noisefloor

  • Hallo Experten, vielen Dank für Eure Hinweise, bin wieder "am Werk":


    Frage an bootsman:

    Die Idee meinen Code in Funktionen aufzuteilen ist mir auch schon gekommen, nur weiss ich noch nicht genau wie.

    1.Was bedeutet pass in Deinem Beispiel ? Ich meine da müssten die entsprechenden Zeilen mit Variablen stehen..

    2. M.E. müsste jede dieser Funktionen durch eine PIR Auslösung pir.when_motion = ....aufgerufen werden.

    luemar

  • meinen Code in Funktionen aufzuteilen ist mir auch schon gekommen, nur weiss ich noch nicht genau wie.

    1.Was bedeutet pass in Deinem Beispiel ? Ich meine da müssten die entsprechenden Zeilen mit Variablen stehen..

    pass ist eine Art Platzhalter, um eine komplett leere Funktion zu definieren, aber dennoch gültigen Python-Code zu schreiben. Vergleichbar mit NOOP, würde ich sagen. Es wird einfach nichts gemacht und implizit None zurückgegeben.

    Dort gehört dann der Jeweilige Code hin.


    Was du mit 2. meinst, weiß ich nicht.

  • ..ja, das das ist mir klar geworden.

    Mit 2. meinte ich, dass jede Funktion - Zähler, Camera Aufnahme, Benachrichtigung per SMS senden, Foto mit email schicken - durch den PIR

    d.h. durch die Erkennung eins Spannungsanstieges am Pin 11 aufgerufen werden muss.

    In meinem derzeitigen Script habe ich die 4 oben erwähnten " quasi Funktionen" direkt als Code in die Funktion

    Code
    def on_motion ():
        # Zähler
        # Camera Aufnahme
        # SMS senden
        # Foto mit email schicken
    pir.when_motion = on_motion


    eingegeben.

    luemar.

  • Hallo linusg und Experten,

    habe (endlich) begriffen wie das mit Funktionen geht und mein Script entsprechen geändert:

    https://gist.github.com/luemar…c26a0beac9fb4f4259aadefd3

    funktioniert soweit problemlos.

    Allerdings musste ich 2 lokale Variable (fn und count) als global setzten, was ja nicht so

    "pythonish" ist aber ich wusste nicht wie das zu umgehen ist.


    Nur, wenn ich mein device über längere Zeit teste passiert folgendes:
    1. Ich starte das Script über PuTTY. Nach einigen h, meistens nachts wenn keine Bewegung ist, quittiert

    PuTTY und damit mein Script. Ich muss dann das Script wieder neu starten.

    Ich vermute eine timeout Funktion bei PuTTY (die man vielleicht deaktivieren könnte ?) habe aber nichts

    gefunden.

    Und ich wäre um einen Hinweis dankbar wie ich die entsprechende Fehlermeldung loggen könnte.


    2. Nachdem das eben passiert ist musst ich meinen Router rebooten um über PuTTYwieder Zugriff

    auf meinen RPI zu bekommen, etwas ganz neues.


    Ich habe die Problematik 1. und 2. auch auf dem englischsprachigen Raspberry Pi Forum gepostet, nach dem

    ich vorübergehend keinen Zugriff auf diese Website hatte.

    Frohes Eiersuchen, Luemar.


    Das Problem 2. wird immer schlimmer, ich muss den router mindestens ein Mal am Tag neu starten.

    Unerklärlicherweise wird der RPI 3

    a) in meiner router Website mit der Liste der verbundenen Geräte meistens als verbunden angezeigt

    b) funktioniert die WLAN Verbindung der übrigen, angezeigten Geräte normal und

    c) erhalte ich die in /etc/crontab eingestellten Scripts per email ganz regulär.
    ??????????????????

    Luemar.

    Edited once, last by luemar: genauere Beschreibung des 2. Problems ().

  • 1. Ich starte das Script über PuTTY. Nach einigen h, meistens nachts wenn keine Bewegung ist, quittiert PuTTY und damit mein Script. Ich muss dann das Script wieder neu starten.

    Hallo luemar,


    nohup oder screen sollten hier Abhilfe schaffen, dann kannst Du Dich auch abmelden und Dein Skript läuft weiter.


    Grüße, STF

  • Allerdings musste ich 2 lokale Variable (fn und count) als global setzten, was ja nicht so

    "pythonish" ist aber ich wusste nicht wie das zu umgehen ist.

    In dem du überlegst warum du global brauchst.


    Am Beispiel fn: Hier steht ja bloss dein Dateiname drin, keinen Grund sowas global zu setzen. Am sinnvollsten ist es eh, wenn man den Dateinamen der Foto Funktion übergibt, so kann man nach belieben neue Bilder erzeugen.


    Code
    def foto(pfad_zum_foto):    
        camera = picamera.PiCamera()    
        camera.capture(pfad_zum_foto, resize=(640, 480))   
        camera.close()

    und hier der passende Teil aus der Mailfunktion

    Code
    def mail(pfad_zum_foto):
    #ehemals f = open..
        with open(pfad_zum_foto, 'rb') as f:
            img = MIMEImage(f.read())    

    in deiner on_motion funktion setzt du dann den Dateinamen und und übergibst den an die anderen Funktionen

    Code
    def on_motion():
        pfad = "/home/pi/bild1.jpg"   
        foto(pfad)    
        mail(pfad)    
        mes()

    Der Unterschied zwischen Genie und Wahnsinn definiert sich im Erfolg.

  • also mein Problem mit PuTTY scheint gelöst:

    Lösung 1: In der PuTTY Configuration/Connection Enable TCP keepalive aktivieren und

    Seconds between keepalives auf 5 setzen.

    Lösung 2: tmux (anstelle von nohup oder screen).

    Habe nicht gewusst, dass wenn PuTTY "quittiert" auch das in der Sitzung gestartete Script beendet wird.


    Werde mein Script korrigieren, ohne globale Variable und dann dieses Thema schliessen.


    Für das WLAN Problem öffne ich eine neue Sitzung

    Nochmals vielen Dank, Luemar.