Fehlermeldung im While-Loop ignorieren

  • Moin, ich betreibe eine Überwachungskamera, die - wenn ein PIR auslöst - ein Video aufnimmt und dies auf einem angeschlossenem USB-Stick speichert.



    Es klappt auch alles wie es soll. Logischerweise gibt es, wenn ich den Stick ziehe und gerade eine Aufnahme läuft, eine Fehlermeldung und ich fliege aus der Dauerschleife.

    Gibt es eine Softwaremöglichkeit, das zu verhindern? Oder hilft nur ein "button", der die Aufnahme abbricht und mir Zeit gibt den Stick zu entfernen? ^^

    Sonst muss ich den Pi immer vom Strom nehmen und wieder anschließen.


    Gruß, Tom

  • Code
    Traceback (most recent call last):
      File "/home/pi/Desktop/camera.py", line 20, in <module>
        record()
      File "/home/pi/Desktop/camera.py", line 12, in record
        camera.start_recording('/media/pi/USB2/{:%d.%m.%Y - %H-%M-%S}.h264'.format(datetime.now()))
      File "/usr/lib/python3/dist-packages/picamera/camera.py", line 1043, in start_recording
        camera_port, output_port = self._get_ports(True, splitter_port)
      File "/usr/lib/python3/dist-packages/picamera/camera.py", line 562, in _get_ports
        'The camera is already using port %d ' % splitter_port)
    picamera.exc.PiCameraAlreadyRecording: The camera is already using port 1 


    Ich dachte einfach an eine generelles "except IOError". Solange, wie kein Fehler verursacht wird, nimm auf.

  • Das Entfernen eines Datenspeichers während eines Schreibzugriffes kannst Du softwaremässig nicht verhindern. Dabei wird jedes Filesystem korrupt. Da ist ausschliesslich die Hard- und Software gefragt, die vor dem Pi (oder PC) sitzt. Und das ist auch bei Windows so, wenn Du den Datenträger nicht "aushängst" (umountest).



    Servus !

    RTFM = Read The Factory Manual, oder so

  • Zeile 10 kann aber nicht von IOError abefangen werden. :conf: Wenn musst du explizit den Fehler abfangen, der auftritt.


    An deiner Stelle würde ich einen kleinen Taster ranbauen, wird dieser gedrückt lässt du über dein Python Skript den USB Stick aushängen und hältst die Schleife an bzw beendest dein Skript.

    Über eine UDEV Regel startet du dein Skript wieder wenn der Stick eingesteckt wurde.

    https://wiki.ubuntuusers.de/udev/

  • Du könntest versuchen das mit:

    Code
    except Exception as e:
        print(e)

    abzufangen. Ob das in dem Fall geht kann ich dir jetzt nicht sagen.


    Ansonsten, wie Hofei schon schrieb wäre es eleganter wenn du einen Button einpflegst.

  • Alternativ geht doch auch eine LED, die grün leuchtet, wenn nichts geschrieben wird, oder? Man müsste das Script ensprechend anpassen, dass der Stick dann gemountet wird, wenn geschrieben wird und unmounted, wenn der Schreibvorgang abgeschlossen ist. So kann man zumindest sehen, wenn der Stick abgezogen werden kann.

  • Ich habe das selbst noch nie gemacht, aber google weiß sicherlich die Antwort ;)

    Es ist natürlich eine Frage, wie oft da geschrieben wird und wie oft /mount/unmount durchgeführt wird. Wenn viele Auslösungen stattfinden ergibt es eventuell mehr Sinn den vorgeschlagenen Button einzubauen.


  • Nachdem die passende Exception gefunden worden ist, die Exception ersetzen:

    Code
    try:
        ...
    except (IOError, PermissionError, PiCameraAlreadyRecording):
        ...

    Man kann mehrere Exceptions in einer Tupel zusammenfassen.


    Das Objekt PiCameraAlreadyRecording muss auch importiert werden.

    Habe ich im ersten Teil des Codes gemacht.


    Welches Exceptions wirklich kommen, musst du einfach mal ausprobieren.

    • Official Post

    picamera.exc.PiCameraAlreadyRecording: The camera is already using port 1

    Wenn ich das richtig verstehe, dann wird der Port noch von der Cam durch die Aufnahme belegt, weil die Aufnahme nicht gestoppt wurde / die Zeile camera.stop_recording() nicht erreicht wurde.

    D.h. den Fehler picamera.exc.PiCameraAlreadyRecording abfangen, aber nicht einfach mit pass übergehen, sondern die Aufnahme stoppen. Das könnte auch wieder einen Fehler werfen und das Video wäre trotzdem kaputt oder nur unvollständig, weil der Datenträger vorher nicht ausgeworfen und damit kein sync ausgeführt wurde.


    //Edit: Hab wieder zu lange rumgemehrt.

  • Hallo,

    Geht das mit Python und weiß auch jemand wie ?

    Was meinst du? Den Stick ein- und ausbinden? Wenn ja, dann kannst du das einfach mit 'subprocess' machen.

    Für weitere Operationen mit USB-Sticks oder ähnliches bietet pyudev interessante Optionen an.

    Falls ich dich falsch verstanden habe, ignoriere den Beitrag einfach.


    Grüße

    Dennis

    ... ob's hinterm Horizont wirklich so weit runter geht oder ob die Welt vielleicht doch gar keine Scheibe ist?

  • Es ist natürlich eine Frage, wie oft da geschrieben wird

    Und wenn ein noch so grosser USB-Stick angesteckt wird, ist - je nach Filesystem - ist nach 64/128/256 Files in erster Ebene Schluss.


    Und ein Ergänzung auf

    Code
    while True:    
        pir.wait_for_motion()     
        mount_and_led_on()
        record()
        umount_and_led_off()

    dürfte nicht so schwierig sein, wenn es nur darum geht, zum Sticktausch den User auf einen Schreibzugriff hinzuweisen.

    Zum Sticktausch kann natürlich auch das ganze Scrip gestoppt und der Stick ugemountet werden.


    Servus !

    RTFM = Read The Factory Manual, oder so

    • Official Post

    Bin nicht sicher wie zeitkritisch das ganze in Verbindung mit einem PIR ist, dazu müsste man das Szenario genauer kennen.


    Angenommen es geht um das Überwachen einer Katzenklappe o.ä. Der PIR löst aus, das Laufwerk wird gemountet, die Cam wird initialisiert und die Aufnahme beginnt dann erst. In dieser Zeit kann sich der Waschbär schon am Futternapf der Katze in der Küche bedienen, während die Cam das Schaukeln der Klappe 45 Sekunden lang aufnimmt. :conf: Rückwärts das selbe Spiel. Der Waschbär ist satt und die Katze, die morgens nach hause kommt, mauzt so lange, bis Tillmario endlich wach wird, aufsteht und ihr Futter gibt. :lol:

  • hyle Selbst wenn die Kamera sofort auslösen würde, wüsste Tillmario am nächsten Tag nur, dass ein Waschbär das Essen gefuttert hat - weg wäre es trotzdem. Und wach wäre er auch früh ;)


    Aber hast natürlich Recht ;)

  • Und wenn ein noch so grosser USB-Stick angesteckt wird, ist - je nach Filesystem - ist nach 64/128/256 Files in erster Ebene Schluss.

    Welche denn? Es käme nur FAT32, exFat und NTFS für Windows infrage.


    Bei FAT32 kann man 2**28 Dateien erstellen. Ein Limit für Dateien im Hauptverzeichnis/Unterverzeichnissen konnte ich nicht finden.

    Also das würde mich jetzt interessieren, welches Dateisystem nur so wenig Dateien in einem Verzeichnis anlegen kann.


    Für den USB-Stick würde ich exFat oder f2fs verwenden. Wenn er an einem Windows-Rechner verwendet werden soll, dann exFat.

  • Der Wikipedia-Artikel zum FAT-Design sagt für FAT32 das Gegenteil eines speziellen Limits für das Hauptverzeichnis. Da steht, dass bei FAT12/FAT16 der Platz für das Hauptverzeichnis beim formatieren mit einer festen Grösse im voraus festgelegt wird und zwischen FAT und Datenbereich liegt, während bei FAT32 das Hauptverzeichnis ganz normal wie alle anderen Verzeichnisse im Datenbereich abgelegt wird und dynamisch wächst.

    “The most likely way for the world to be destroyed, most experts agree, is by accident. That's where we come in; we're computer professionals. We cause accidents.” — Nathaniel Borenstein

  • Hallo, danke für eure vielen Tipps.

    Wieso speicherst du nicht direkt auf dem Pi und schiebst die Aufnahmen zu definierten Zeiten auf den Stick?

    So habe ich es jetzt erstmal gemacht. Klappt super und ist für die Anwendung wunderbar geeignet. Jeden morgen um 1 Uhr wird versucht, die Daten vom Pi auf den Stick zu schieben. Das reicht aus am Folgetag erst die Daten zu haben. (Es ist für einen mobilen Hühnerstall um Diebe zu erwischen)


    Danke besonders DeaD_EyE für deine Mühe. Ich verstehe aber noch nicht, wie genau ich jetzt das Zweite beim Ersten ersetzen soll.

    Code
    [...]
        except Exception as e:
            print("Exception-Name:", e.__class__.__qualname__)
            print("Exception from Module:", e.__class__.__module__)
            # um der aufrufenden Funktion den Misserfolg mitteilen zu können
            # ein False zurückliefern
            return False


    Nachdem die passende Exception gefunden worden ist, die Exception ersetzen:

    Code
    try:
        ...
    except (IOError, PermissionError, PiCameraAlreadyRecording):
        ...

    Gruß, Tom