Anmelden

Archiv verlassen und diese Seite im Standarddesign anzeigen : LibreELEC - Probleme mit Python-Script mit gpiozero


Korfox
2025-01-01, 17:18:29
Moin Gemeinde,

ich habe LibreELEC auf einem RaspberryPi 4B. Der Raspi sitzt in einem Retroflag Nespi4 und ich bin gerade daran am Verzweifeln die Knöpfe und LED des Gehäuses sinnvoll zum Funktionieren zu bekommen.
Also prinzipiell tut es, was es soll, aber der Autostart tut nicht (und der Lüfter geht nach dem Shutdown nicht aus).

Vielleicht kann mir jemand hier helfen.
Gesamtskript (bisher):
import sys
sys.path.append('/storage/.kodi/addons/virtual.rpi-tools/lib/')
from gpiozero import LED,Button
import os
import time
from multiprocessing import Process

#initialize pins
powerPin = 3 #pin 5
ledPin = 14 #TXD
resetPin = 2 #pin 13
powerenPin = 4 #pin 5

btnReboot = Button(resetPin)
btnPower = Button(powerPin)
led = LED(ledPin)
led.on()
powerLed = LED(powerenPin)
powerLed.on()

#initialize GPIO settings
def rebootButton():
while True:
if btnReboot.is_pressed: rebootButtonPressed()
def powerButton():
while True:
if btnPower.is_pressed: powerButtonPressed()

def powerButtonPressed():
os.system("kodi-send -a \"Notification(Power Button Pressed, Shutting down in 5 seconds)\"")
led.blink(on_time=0.2,off_time=0.2,n=None,background=True)
time.sleep(5)
if btnPower.is_pressed:
os.system("systemctl stop kodi && sleep 5s && shutdown -h now")
else:
led.on()
def rebootButtonPressed():
os.system("kodi-send -a \"Notification(Reset Button Pressed, Restarting Kodi/Rebooting)\"")
led.blink(on_time=0.2,off_time=0.2,n=None,background=True)
time.sleep(2)
if btnReboot.is_pressed:
os.system("systemctl stop kodi && sleep 5s && shutdown -r now")
led.on()
else:
os.system("kodi-send -a \"RestartApp\"")
led.on()
if __name__ == "__main__":
#initialize GPIO settings
rebootProcess = Process(target = rebootButton)
rebootProcess.start()
shutdownProcess = Process(target = powerButton)
shutdownProcess.start()

shutdownProcess.join()
rebootProcess.join()


Das script lässt sich problemlos per Kommando aufrufen:
/storage/.config/autostart.sh
enthält
GNU nano 7.2 /storage/.config/autostart.sh
python /storage/scripts/shutdown.py &

und ein manueller Aufruf der autostart.sh führt dazu, dass alles soweit funktioniert (wie gesagt: Der Lüfter geht nicht aus, wenn das System anhält).

Jetzt zum Knackpunkt:

systemctl status kodi-autostart
liefert
Jan 01 16:55:08 LibreELEC systemd[1]: Finished kodi-autostart.service.
● kodi-autostart.service - Kodi user autostart script
Loaded: loaded (/usr/lib/systemd/system/kodi-autostart.service; disabled; preset: disabled)
Active: active (exited) since Wed 2025-01-01 17:08:01 CET; 4s ago
Process: 1751 ExecStart=/bin/sh -c . /etc/profile; test -f /storage/.config/autostart.sh && exec /bin/sh /storage/.config/autostart.sh (code=exited, status=0/SUCCESS)
Main PID: 1751 (code=exited, status=0/SUCCESS)
● kodi-autostart.service - Kodi user autostart script
Loaded: loaded (/usr/lib/systemd/system/kodi-autostart.service; disabled; preset: disabled)
Active: active (exited) since Wed 2025-01-01 17:08:01 CET; 6min ago
Process: 1751 ExecStart=/bin/sh -c . /etc/profile; test -f /storage/.config/autostart.sh && exec /bin/sh /storage/.config/autostart.sh (code=exited, status=0/SUCCESS)
Main PID: 1751 (code=exited, status=0/SUCCESS)
Tasks: 0 (limit: 3923)
CPU: 690ms
CGroup: /system.slice/kodi-autostart.service

Jan 01 17:08:01 LibreELEC sh[1787]: self.pin.edges = 'both'
Jan 01 17:08:01 LibreELEC sh[1787]: ^^^^^^^^^^^^^^
Jan 01 17:08:01 LibreELEC sh[1787]: File "/storage/.kodi/addons/virtual.rpi-tools/lib/gpiozero/pins/__init__.py", line 441, in <lambda>
Jan 01 17:08:01 LibreELEC sh[1787]: lambda self, value: self._set_edges(value),
Jan 01 17:08:01 LibreELEC sh[1787]: ^^^^^^^^^^^^^^^^^^^^^^
Jan 01 17:08:01 LibreELEC sh[1787]: File "/storage/.kodi/addons/virtual.rpi-tools/lib/gpiozero/pins/native.py", line 519, in _set_edges
Jan 01 17:08:01 LibreELEC sh[1787]: self.factory.fs.export(self._number)
Jan 01 17:08:01 LibreELEC sh[1787]: File "/storage/.kodi/addons/virtual.rpi-tools/lib/gpiozero/pins/native.py", line 251, in export
Jan 01 17:08:01 LibreELEC sh[1787]: with io.open(self.path('export'), 'wb') as f:
Jan 01 17:08:01 LibreELEC sh[1787]: OSError: [Errno 22] Invalid argument

Entsprechend wird das Skript nicht automatisch gestartet.
Das Minimalbeispiel, ab dem der Fehler auftritt:
import sys
sys.path.append('/storage/.kodi/addons/virtual.rpi-tools/lib/')
from gpiozero import LED,Button
import os
import time
from multiprocessing import Process

#initialize pins
powerPin = 3 #pin 5
ledPin = 14 #TXD
resetPin = 2 #pin 13
powerenPin = 4 #pin 5

btnPower = Button(powerPin)


Wenn ich nur die LEDs schalten möchte kommt noch ein weiterer Fehler.
import sys
sys.path.append('/storage/.kodi/addons/virtual.rpi-tools/lib/')
from gpiozero import LED,Button
import os
import time
from multiprocessing import Process

#initialize pins
powerPin = 3 #pin 5
ledPin = 14 #TXD
resetPin = 2 #pin 13
powerenPin = 4 #pin 5

led = LED(ledPin)
led.on()

führt also zu
Jan 01 17:17:34 LibreELEC systemd[1]: Finished kodi-autostart.service.
Jan 01 17:17:35 LibreELEC sh[1903]: 2025-01-01 17:17:35 xCreatePipe: Can't set permissions (436) for //.lgd-nfy0, No such file or directory
Jan 01 17:17:35 LibreELEC sh[1903]: /storage/.kodi/addons/virtual.rpi-tools/lib/gpiozero/devices.py:300: PinFactoryFallback: Falling back from lgpio: [Errno 2] No such file or directory: '.lgd-nfy-3'
Jan 01 17:17:35 LibreELEC sh[1903]: warnings.warn(
Jan 01 17:17:35 LibreELEC sh[1903]: /storage/.kodi/addons/virtual.rpi-tools/lib/gpiozero/devices.py:300: PinFactoryFallback: Falling back from rpigpio: No module named 'RPi'
Jan 01 17:17:35 LibreELEC sh[1903]: warnings.warn(
Jan 01 17:17:35 LibreELEC sh[1903]: /storage/.kodi/addons/virtual.rpi-tools/lib/gpiozero/devices.py:300: PinFactoryFallback: Falling back from pigpio: No module named 'pigpio'
Jan 01 17:17:35 LibreELEC sh[1903]: warnings.warn(
Jan 01 17:17:35 LibreELEC sh[1903]: /storage/.kodi/addons/virtual.rpi-tools/lib/gpiozero/devices.py:297: NativePinFactoryFallback: Falling back to the experimental pin factory NativeFactory because no other pin factory could be loaded. For best results, install RPi.GPIO or pigpio. See https://gpiozero.readthedocs.io
Jan 01 17:17:35 LibreELEC sh[1903]: warnings.warn(NativePinFactoryFallback(native_fallback_message))


Anyone any idea?

konkretor
2025-01-02, 10:41:53
gpiozero hast du korrekt installiert?

https://gpiozero.readthedocs.io/en/latest/installing.html#raspberry-pi

sonst mal prüfen was er da ausgibt

pip3 show gpiozero

mit
gpio readall

kannst du schauen ob nicht noch ein anderes Prozess drauf zugreift oder Fehlermeldung gibt.

Haufen
2025-01-02, 13:09:35
In den beiden Endlosschleifen (while True) gibt es keine Abbruchbedingung, sodass sich die beiden Prozesse beenden können, wenn eine der Tasten betätigt worden ist. D.h., die Prozesse laufen weiter auf Volldampf, weil auch kein kurzes Warten eingebaut ist.
Ist das egal, weil unter Linux die Prozesse beim Neustart/Abschalten zwangsbeendet werden?

Korfox
2025-01-02, 15:27:54
gpiozero hast du korrekt installiert?

https://gpiozero.readthedocs.io/en/latest/installing.html#raspberry-pi

sonst mal prüfen was er da ausgibt

pip3 show gpiozero

mit
gpio readall

kannst du schauen ob nicht noch ein anderes Prozess drauf zugreift oder Fehlermeldung gibt.
In LibreELEC ist das nichts mit pip/pip3. Das ist eine Minimaldistribution. gpiozero wird da mit dem Raspberry Pi Tools-Addon installiert (daher auch der sys.path.append-Befehl).
Ansonsten läuft das Skript ja bei manueller Ausführung völlig problemlos (vom Lüfer abgesehen), was darauf hindeutet, dass gpiozero korrekt installiert ist und auch funktioniert.
Ich werde Mal schauen, ob ich es hinbekomme, dass gpio readall zum Systemstart ausgeführt wird. Weil genau dann ja das Problem auftritt.

In den beiden Endlosschleifen (while True) gibt es keine Abbruchbedingung, sodass sich die beiden Prozesse beenden können, wenn eine der Tasten betätigt worden ist. D.h., die Prozesse laufen weiter auf Volldampf, weil auch kein kurzes Warten eingebaut ist.
Ist das egal, weil unter Linux die Prozesse beim Neustart/Abschalten zwangsbeendet werden?

Danke für den Input. Das mit den Endlosschleifen sollte schmerzfrei sein. Bei einem shutdown werden alle Prozesse gekillt. Deswegen hatte ich aber auch die beiden Minimalbeispiele angehängt, weil da deutlich wird, dass die Deklaration der LED/Buttons schon scheitert. Also der Zugriff auf gpiozero.


Wie geschrieben:
Führe ich zur Laufzeit die autostart.sh manuell aus (also als root per SSH - LibreELEC kennt nur einen User und der ist root) läuft das Skript soweit korrekt.
Ich vermute tatsächlich aber beim Systemstart Zugriffsrechtsprobleme (wobei es ja nur root gibt?!) und beim Lüfter ein Problem mit den Haltstates (da muss ich in der config.txt noch etwas spielen, vermute ich... da hat sich mit dem Pi400 etwas geändert IIRC, damit der auf Knopfdruck wieder starten kann).

Korfox
2025-01-25, 12:37:05
Problem solved (außer, dass der Lüfter nicht aus geht).
Gpiozero schreibt auf den Datenträger in das aktuelle Verzeichnis. Das ist beim Autostart-Deamon... Problematisch 🤣. Ein einfacher Wechsel in ein temporäres Verzeichnis am Anfang der autostart.sh erledigt den Rest.

Korfox
2025-01-25, 14:24:19
Ok. Das Problem ist jetzt vollständig gelöst.
Was man nicht alles tut, wenn der Router abgeraucht ist und man kein Internet hat...

Die /.config/autostart.sh:
cd /storage/.kodi/temp/
python /storage/scripts/shutdown.py &

Die /flash/config.txt:

#dtoverlay=RetroFlag_pw_io.dtbo
dtoverlay=gpio-poweroff,gpiopin=4,active_low=1,input=1
#enable_uart=1

(Ich habe die beiden auskommentierten Konfigurationen Mal bewusst drin gelassen)

Und schließlich die /storage/scripts/shutdown.py:

import sys
sys.path.append('/storage/.kodi/addons/virtual.rpi-tools/lib/')
from gpiozero import LED,Button
import os
import time
from multiprocessing import Process

#initialize pins
powerPin = 3 #pin 5
ledPin = 14 #TXD
resetPin = 2 #pin 13

btnReboot = Button(resetPin)
btnPower = Button(powerPin)
led = LED(ledPin)
led.on()

def rebootButton():
while True:
if btnReboot.is_pressed: rebootButtonPressed()
def powerButton():
while True:
if btnPower.is_pressed: powerButtonPressed()

def powerButtonPressed():
os.system("kodi-send -a \"Notification(Power Button Pressed, Shutting down in a few seconds)\"")
led.blink(on_time=0.2,off_time=0.2,n=None,background=True)
time.sleep(1)
if btnPower.is_pressed:
os.system("systemctl stop kodi && sleep 1s && shutdown -h now")
else:
led.on()
def rebootButtonPressed():
os.system("kodi-send -a \"Notification(Reset Button Pressed, Restarting Kodi/Rebooting)\"")
led.blink(on_time=0.2,off_time=0.2,n=None,background=True)
time.sleep(1)
if btnReboot.is_pressed:
os.system("systemctl stop kodi && sleep 1s && shutdown -r now")
led.on()
else:
os.system("kodi-send -a \"RestartApp\"")
led.on()
if __name__ == "__main__":
rebootProcess = Process(target = rebootButton)
rebootProcess.start()
shutdownProcess = Process(target = powerButton)
shutdownProcess.start()

shutdownProcess.join()
rebootProcess.join()