GPIO mit Root Rechten innerhalb von Pycharm ansprechen

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
MainzerKaiser
User
Beiträge: 14
Registriert: Mittwoch 5. Januar 2022, 08:59

Hallo,
Ich versuche meine Pythonprogramme zur Steuerung einer LED Leiste mit GUI über PyQt und mit pycharm als IDE zu programmieren. In dem Pycharm Projekt stecken Routinen zur Ansteuerung der GPIO Pins, die ich vorher einzeln zum Test außerhalb von pycharm per sudo mit root Rechten starten musste. Ohne Root Rechte komme ich wohl nicht an die entsprechenden Pins ran.
Es geht um eine LED Leiste von adafruit (https://learn.adafruit.com/neopixels-on ... -3005997-2), die auf ihrer Website auch die Notwendigkeit von root herausstellen, weil auf /dev/mem zugegriffen werden muss.

Ich habe in Pycharm den Weg über ein Shell Skript als Interpreter statt direkt Python3.7 genutzt, wie hier beschrieben:
https://esmithy.net/2015/05/05/rundebug ... 0as%20root


Im Grunde setzt das shell skript ein sudo vor das python, welches in der virtuellen Umgebung des Pycharm Projektes genutzt wird:

Code: Alles auswählen

sudo /home/pi/PycharmProjects/LEDStrip/venv/bin/python3.7 main.py
Wenn ich das Projekt nun debugge, oder die Zeile im Terminal von pycharm teste, bekomme ich:

Code: Alles auswählen

No protocol specified
qt.qpa.screen: QXcbConnection: Could not connect to display :10.0
Could not connect to any X display.
In der main.py wird eine qt Fenster geöffnet, was anscheinend schief läuft.

Vermutlich stimmen die Pfade und Umgebungsvariablen nicht.

Wenn ich dem "sudo" ein "su pi" anfüge, um nach meiner Interpretation den Benutzer "pi" mit "su" zum Benutzer "root" zu machen,

Code: Alles auswählen

sudo su pi /home/pi/PycharmProjects/LEDStrip/venv/bin/python3.7 main.py
oder 
sudo su - pi /home/pi/PycharmProjects/LEDStrip/venv/bin/python3.7 main.py
führt das zu

Code: Alles auswählen

/home/pi/PycharmProjects/LEDStrip/venv/bin/python3.7: /home/pi/PycharmProjects/LEDStrip/venv/bin/python3.7: Kann die Datei nicht ausführen.
Die andere Schreibweise mit

Code: Alles auswählen

sudo -su pi /home/pi/PycharmProjects/LEDStrip/venv/bin/python3.7 main.py
lässt die GUI starten führt dann aber zum gleichen Problem, als wenn ich ohne sudo arbeite und das pycharm Projekt ganz normal nur als pi durchführe:

Code: Alles auswählen

libEGL warning: DRI2: failed to authenticate
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-pi'
Main GUI Start
Main LED Star Methode
In LEDStart
Can't open /dev/mem: Keine Berechtigung
Traceback (most recent call last):
  File "main.py", line 150, in LEDStartfunct
    LEDStart(self)
  File "main.py", line 135, in LEDStart
    strip.begin()
  File "/home/pi/PycharmProjects/LEDStrip/venv/lib/python3.7/site-packages/rpi_ws281x/rpi_ws281x.py", line 131, in begin
    raise RuntimeError('ws2811_init failed with code {0} ({1})'.format(resp, str_resp))
RuntimeError: ws2811_init failed with code -5 (mmap() failed)
Abgebrochen
Wenn man nach den Fehlermeldungen googelt, bekommt man den Hinweis, dass man mit sudo arbeiten muss um root-Rechte zu gewähren.

Scheinbar bedeutet sudo -su pi, dass ich nicht mit root Rechten als Benutzer pi weiterarbeite, sondern, dass ich mit pi Rechten als pi weiterarbeite. Kann das stimmen?



Hier noch die Ausgabe von groups und pi:

Code: Alles auswählen

Hier mal die Ausgabe von id und groups für den Benutzer pi:
Code

pi@raspberrypi:~/LED Strip Tutorial $ groups
pi adm kmem dialout cdrom sudo audio video plugdev games users input netdev lpadmin gpio i2c spi
pi@raspberrypi:~/LED Strip Tutorial $ id
uid=1000(pi) gid=1000(pi) Gruppen=1000(pi),4(adm),15(kmem),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(games),100(users),105(input),109(netdev),117(lpadmin),997(gpio),998(i2c),999(spi)
Außerdem, sowohl die main.py, als auch der Link python3.7 in der venv des pycharm Projektes haben Zugriffsrechte per chmod 777.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ja, das sudo sich so verhält, ist richtig. Es ist allgemein dazu gedacht, Kommandos als anderer User auszuführen. Nicht nur Root. Wenn du den User Pi angibst, dann ist der das.

Die anderen Probleme sind Xorg-Probleme. Du kannst mal mit -E als zusätzliches Argument an sudo versuchen, das vererbt das Environment. Und kann dadurch ggf die DISPLAY Variable erhalten.

Die saubere Lösung wäre ein Dämon mit root-rechten, welcher der GUI seine Dienste mit einer ohne Privilegien nutzbaren Schnittstelle Anbietet.
MainzerKaiser
User
Beiträge: 14
Registriert: Mittwoch 5. Januar 2022, 08:59

Danke für die Tipps,
der Tipp mit dem Argument -E löst leider noch nicht mein Problem.
sudo -E /home/pi/PycharmProjects/LEDStrip/venv/bin/python3.7 main.py
sudo: Sie dürfen das Environment nicht erhalten
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die deutsche Fehlermeldung laesst sich nicht gut suchen, darum finde ich dazu nichts.

Du kannst auch probieren, die DISPLAY-Variable selbst zu setzen, wahrscheinlich geht das in pycharm irgendwie.

Aber wie gesagt, eigentlich will man da eine Trennung von GUI und LED-Strip-Ansteuerung. Sowas gibt es sogar schon fertig: https://github.com/tom-2015/rpi-ws2812-server
Benutzeravatar
hyle
User
Beiträge: 96
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

Alles was wir sind ist Sand im Wind Hoschi.
MainzerKaiser
User
Beiträge: 14
Registriert: Mittwoch 5. Januar 2022, 08:59

hyle hat geschrieben: Mittwoch 5. Januar 2022, 18:18 Zur Vorgeschichte: https://forum-raspberrypi.de/forum/thre ... -ansteuern
Danke! In dem Forum vom RaspPi ist es etwas still geworden.
MainzerKaiser
User
Beiträge: 14
Registriert: Mittwoch 5. Januar 2022, 08:59

__deets__ hat geschrieben: Mittwoch 5. Januar 2022, 17:32 Die deutsche Fehlermeldung laesst sich nicht gut suchen, darum finde ich dazu nichts.

Du kannst auch probieren, die DISPLAY-Variable selbst zu setzen, wahrscheinlich geht das in pycharm irgendwie.

Aber wie gesagt, eigentlich will man da eine Trennung von GUI und LED-Strip-Ansteuerung. Sowas gibt es sogar schon fertig: https://github.com/tom-2015/rpi-ws2812-server
Danke für den Link. Die SVR Version von WS2812 kannte ich in der Tat noch nicht. Noch klingt das für mich wie ein totaler overkill für meine Zwecke. Ich hatte gehofft, dass man das mit ein bisschen Rechte-Management regeln kann. Ich schaue mir das genauer an.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Naja, alles mit root-Rechten zu machen, ist so ziemlich das Gegenteil von Rechtemanagement. Es ist stattdessen das abschenken jeden Versuchs, da mit Rechten zu arbeiten.

Alternativ kannst du den neopixel-Kram auch via pigpiod von PiGPIO machen. Dann geht natuerlich die Adafruit-Library so direkt zumindest nicht, sondern muss darauf angepasst werden. Aber das ist ein sauberer Ansatz, und vermeidet root-Rechte fuer das Anwendungsprogramm. Und sollte auch performant genug sein, wenn die den Direktzugriff auf die IOs wollen. Damit arbeitet der auch.
MainzerKaiser
User
Beiträge: 14
Registriert: Mittwoch 5. Januar 2022, 08:59

​Hallo zusammen,

ich wollte von dem aktuellen Workaround berichten und hätte ein paar Folgefragen.

In der aktuellen Umsetzung wird die GUI vom Benutzer pi genutzt, in der die LED Leiste per QProcess (https://www.pythonguis.com/tutorials/qp ... -programs/) durch den Nutzer root gestartet wird.

Code: Alles auswählen

​
self.p=QProcess()
self.p.start("sudo",["python","LEDStart.py"])
​self.PID=self.p.processId()
Die Parameter für die LED Leiste (Geschwindigkeit, Farbe etc.) werden dann text-basiert per json zwischengespeichert. Das Schwierige an der Sache ist, dass im Gegensatz zu den meisten Prozessen die LED in einer Endlos While-Schleife läuft und die GUI währenddessen nicht einfrieren darf.

Außerdem muss dann mit Betätigen des Stop Buttons der root Prozess mit einem weiteren QProzess gekillt werden. Der zweite QProzess ist ja dann schnell beendet und verschwindet wieder.

Code: Alles auswählen

​self.p2.start("sudo",["kill",str(self.PID+1)])
​Seltsamerweise muss man hier nicht die PID des ersten Prozesses killen, sondern PID+1. Warum, weiß ich noch nicht....

Die GUI läuft an sich gut und ist auch performant genug. Ich suche noch nach Möglichkeiten, die im QCreator vorgegebenen Slider zu vergrößern, weil ich diese auf meinem 7" Touchscreen kaum erwische. Die sind eindeutig für den Betrieb mit der Maus gedacht.

Habt ihr eine Idee, wie man die vorgegebenen widgets in ihren Eigenschaften
verändern kann?​

Vielen Dank für jegliche Ideen!!
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das du PID+1 brauchst ist nicht weiter verwunderlich - schliesslich hat sudo eine PID, und die bekommst du zurueck, und das startet ein Programm, und das hat dann mit ein bisschen Glueck die PID+1. Bis es die nicht mehr hat, weil dazwischen doch aus versehen ein anderer Prozess gestartet wurde. Und dann ist es PID + X.

Der saubere Weg waere hier also, dass das LEDStart.py wie jeder andere Daemon in /var/run zB eine PID-Datei anlegt, ueber die man es dann verlaesslich killen kann. Oder noch besser: einfach als systemd-Service startten.

Bezueglich des Stylings schaue ich immer im Qt Designer, an was man da so rumspielen kann. Aber eigentlich ist fuer solche Oberflaechen auch eher QML gedacht, damit baut man sich sowas recht einfach.
Benutzeravatar
hyle
User
Beiträge: 96
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

Mit

Code: Alles auswählen

sudo pkill -f LEDStart.py
müsste das IMHO auch funktionieren.
Alles was wir sind ist Sand im Wind Hoschi.
MainzerKaiser
User
Beiträge: 14
Registriert: Mittwoch 5. Januar 2022, 08:59

hyle hat geschrieben: Donnerstag 27. Januar 2022, 17:56 Mit

Code: Alles auswählen

sudo pkill -f LEDStart.py
müsste das IMHO auch funktionieren.
Klasse, funzt natürlich sauberer so!
MainzerKaiser
User
Beiträge: 14
Registriert: Mittwoch 5. Januar 2022, 08:59

Die Frage nach der Vergrößerung der Sliders habe ich selber herausfinden können. Das geht über style sheets entsprechend: https://stackoverflow.com/questions/432 ... d/43283147
Antworten