Raspberry Pi GPIO Netzwerkverbindung verloren und erneut versuchen zu verbinden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
bachatero18
User
Beiträge: 43
Registriert: Montag 12. August 2019, 13:57

Hallo zusammen,
ich hab folgenden Problem, ich Frage von einem Computer die GPIO Pins eines Raspberry Pi's der im selben Netzwerk ist, ab.

Es kommt mal vor, dass die Verbindung verloren geht. Im Prinzip soll er nach einer Wartezeit nochmals versuchen die Verbindung aufzubauen.
Das tut er aber nicht auch wenn der Raspberry Pi wieder erreichbar sein sollte. Ich muss das Programm dann jedes mal Neustarten und dann geht es wieder.

Was kann ich tun damit er genau das macht?

Anbei einmal der prinzipielle Aufbau des Python-Programms:

Code: Alles auswählen

from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep

factory = PiGPIOFactory(host='192.168.178.5')
led = LED(17, pin_factory=factory)

while True:
    try:
        if led.is_lit:
            print("ON")
            sleep(5)
        else:
            print("OFF")
            sleep(5)

    except:
        print("Verbindungsfehler")
        sleep(5)
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@bachatero18,

andere haben das Problem wohl auch. Ein "Workaround" ist in diesem Thread beschrieben:
https://github.com/gpiozero/gpiozero/issues/659
imonbln
User
Beiträge: 191
Registriert: Freitag 3. Dezember 2021, 17:07

Ich sehe im Sourcecode der PiGPIOFactory keinen Code für ein Reconnect. In der Property Connection wird geprüft, ob die Connection da ist und wenn nicht, die Exception einfach ignoriert (siehe https://github.com/gpiozero/gpiozero/bl ... #L112-L121) .

IMHO ist das ein Bug in GPIOZero Package. In einer idealen Welt würdest du das mit den Entwicklern diskutieren und das Package verbessern, oder als dreckigen Workaround in der Realität die Factory und led in deiner Exception neu instantiieren.
bachatero18
User
Beiträge: 43
Registriert: Montag 12. August 2019, 13:57

@rogerb
den hatte ich vorhin tatsächlich auch schon gefunden und hatte zu schnell rüber gelesen und das vor schnell als nicht sinnvoll abgestempelt. Hab es jetzt etwas abgeändert er haut mir bei fehlender Verbindungfehler Fehler raus aber bricht halt nicht ab und baut eine Verbindung wieder auf zumindest versucht er es. Except habe ich die expliziten Fehler rausgenommen weil er bei allen das selbe machen soll. Aber das kann ja nicht die Lösung sein.

@imonbln
ja ich warte mal vielleicht hat noch jemand eine gute Idee. Btw aber so ein reconnect wäre schon nice, einfach eine Zeile dazu und fertig.

Code: Alles auswählen

from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep

while True:
    factory = None
    while not factory:
        
        try:
            factory = PiGPIOFactory(host='192.168.178.39')
        except:
            print("Verbindungsfehler")
            sleep(5)
    led = LED(17, pin_factory=factory)
    led.on()
    sleep(5)
    
    try:
        led.close()
        factory.close()
    except:
        print("verbindungsfehler 2")
        continue
Benutzeravatar
__blackjack__
User
Beiträge: 14078
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bachatero18: Das nackte ``except`` geht gar nicht. Was ist wenn da eine Ausnahme kommt die gar nichts mit der Verbindung zu tun hat? Nach so einem Fehler kann man sich dann dusselig suchen.

``sleep(5)`` wir ja letztlich in jedem möglichen Ausgang gemacht, also braucht das da auch nur *einmal* stehen und nicht dreimal.

Code: Alles auswählen

#!/usr/bin/env python3
import struct
from time import sleep

from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOFactory


def main():
    factory = PiGPIOFactory(host="192.168.178.5")
    led = LED(17, pin_factory=factory)

    while True:
        try:
            print("ON" if led.is_lit else "OFF")
        except struct.error:
            print("Verbindungsfehler")
        sleep(5)


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
bachatero18
User
Beiträge: 43
Registriert: Montag 12. August 2019, 13:57

Wie ich es abgeändert hat ist auch nur ein Beispiel damit ich sehe was passiert. Und Sleep() soll auch eher wenn es geht gar nicht rein.

Das stimmt wohl mit den nackten except ich werden es eine Zeit lang laufen lassen und die genauen Fehler abspeichern mit ''sys.exc_info()[0] '' und dann kann ich für jeden Fehler ein eigenes except machen wenn es nötig ist.
bachatero18
User
Beiträge: 43
Registriert: Montag 12. August 2019, 13:57

Weiß jemand wo ich eine Liste finde die ich für PIGPIO alle Funktionen finde die es gibt?

Problem ist gerade wenn ich die Verbindung zum PI schließe schaltet er auch die LED aus die soll aber angeschaltet bleiben. Es liegt wohl an Factory.close()
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

bachatero18 hat geschrieben: Donnerstag 13. Januar 2022, 12:56 Weiß jemand wo ich eine Liste finde die ich für PIGPIO alle Funktionen finde die es gibt?
Am besten direkt an der Quelle:
https://github.com/joan2937/pigpio

Da ist auch eine Dokumentation verlinkt
bachatero18
User
Beiträge: 43
Registriert: Montag 12. August 2019, 13:57

danke.

Weiß du wo ich da genau suchen muss? weil ich persönlich finde da nichts?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist alles Gehampel. PiGPIO ist super, aber es ist nicht dafuer gemacht. Statt zu versuchen darum herumzuhacken, bau dir einfach einen trivialen flask oder FastAPI-webservice, der die Hardware via pigpio lokal & robust kontrolliert, und dann steuerst du aus deinem entfernten Prozess das alles einfach per HTTP-Requests fern.
bachatero18
User
Beiträge: 43
Registriert: Montag 12. August 2019, 13:57

Danke für die Antworten. Ich glaub das bekomm ich nicht hin dafür bin ich noch nicht ausreichend in Python drin.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Man waechst ja an seinen Aufgaben. Was du jetzt vorhast ist auch nicht unkompliziert, und dann auch nur ein Workaround. Ich glaube zB nicht, dass du dein akutes Problem - reset des Levels - geloest bekommst, weil ich in der API nichts dazu sehe. Der geht einfach nicht davon aus, dass man da re-connected, etc.
bachatero18
User
Beiträge: 43
Registriert: Montag 12. August 2019, 13:57

Ja habe jetzt einiges gesucht aber auch nichts gefunden.
Da hast du recht aber das ist glaube ich nicht mal eben schnell gelöst.

Ich bin am überlegen ob ich auf dem Raspberry PI noch ein Script laufen lasse der reagiert wenn ein Pin kurz auf High gesetzt wird und wenn ein anderer Pin kurz auf high gesetzt wird hört er mit der Aufgabe auf.

Ich glaube das ist für meinen Wissensstand erstmal das Beste und es ist erstmal lauffähig. Die Verbesserung werden ich mir bei genügend Zeit anschauen und mal gucken ob ich das hinbekomme
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich wuerde mir ja erstmal anschauen, wie kompliziert es wirklich ist, einen Webservice zu bauen. Das ist ja nicht so, als ob das nicht tausendfach passiert waere, um eben zB GPIOs ueber eine Webseite zu steuern. Aber ist natuerlich dein Problem.
bachatero18
User
Beiträge: 43
Registriert: Montag 12. August 2019, 13:57

Ok das sah jetzt beim rüberfliegen nicht so schwierig aus ich glaube das packe ich aber ich lass mir zeit.

Danke für die Hilfe
Benutzeravatar
DeaD_EyE
User
Beiträge: 1244
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

__deets__ hat geschrieben: Donnerstag 13. Januar 2022, 13:55 Das ist alles Gehampel. PiGPIO ist super, aber es ist nicht dafuer gemacht. Statt zu versuchen darum herumzuhacken, bau dir einfach einen trivialen flask oder FastAPI-webservice, der die Hardware via pigpio lokal & robust kontrolliert, und dann steuerst du aus deinem entfernten Prozess das alles einfach per HTTP-Requests fern.
Er hat FastAPI geschrieben <3
Eine gewisse Einarbeitung ist dennoch erforderlich.
Ob jetzt mit RPi.GPIO oder pigpio oder gpiozero gearbeitet wird, ist egal.

Code: Alles auswählen

from __future__ import annotations

import atexit
from typing import Literal

try:
    from RPi import GPIO as gpio
except ImportError:
    from unittest.mock import Mock

    gpio = Mock()

from pydantic import BaseModel
from fastapi import FastAPI
from fastapi.exceptions import HTTPException
from fastapi.responses import RedirectResponse


api = FastAPI()
ON_OFF = Literal[0, 1]

gpio.setup(gpio.BCM)
# gpio.setmode([2, 3, 4, 5, 6, 7], gpio.OUTPUT)
atexit.register(gpio.cleanup)


class ReadResponse(BaseModel):
    """
    Status des gelesenen GPIO Pin
    """

    pin: int
    state: bool


@api.get("/")
def root():
    """
    Umleitung zur Dokumentation
    """

    return RedirectResponse("/docs")


@api.get("/read/{pin}", response_model=ReadResponse)
def read(pin: int):
    """
    GPIO Pin lesen
    """

    try:
        state = bool(gpio.input(pin))
        # 1 / 0
    except Exception as e:
        raise HTTPException(404, e.args[0])

    return {"pin": pin, "state": state}


@api.post("/read/{pin}/{value}")
def write(pin: int, value: ON_OFF):
    """
    GPIO Pin setzen
    """

    try:
        gpio.output(pin, value)
        state = bool(gpio.input(pin))
        # 1 / 0
    except Exception as e:
        raise HTTPException(404, e.args[0])

    return {"pin": pin, "state": state}


# dann das Script mittels uvicorn von der Kommandozeile starten:
# uvicorn datei_ohne_erweiterung:api

sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten