jms3000
Anmeldungsdatum: 29. Januar 2015
Beiträge: Zähle...
|
Ich habe einen Intel nuc7pjy mit einem eingebauten IR-Empfänger/Sender. Ohne lirc oder lircd zu benutzen möchte ich mit Python die IR-Signale lesen.
Mit ir-keytable habe ich die Zuordnung Signal->Befehl gemacht.
Dann lasse ich dieses Programm laufen:
| import evdev
device = evdev.InputDevice('/dev/input/event12')
for event in device.read_loop():
print(evdev.categorize(event))
|
Das funktioniert, aber "event12" ist leider hardcodiert. Ich habe es aus der Ausgabe von ir-keytable. Wie finde ich denn die Eventnummer mit Python raus?
Was ich herausgefunden habe: es gibt den Pfad /sys/class/rc/rc0, der steht wohl für den IR-Empfänger. Und dazu gibt es dann den Pfad /sys/class/rc/rc0/input24/event12, da findet man dann das event12. In /sys/class/rc/rc0/input24/event11/uevent steht dann das input-event drin.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 10978
|
Am besten schaust du mit pyudev nach einem Empfänger, der die gewünschten Eigenschaften hat oder legst mit einer udev-Regel einen eindeutigen Symlink auf das Input Device an. Zum Lesen vom Device könnte man z.B. evdev nutzen, das abstrahiert die unterschiedlichen Events schön, so dass man die bequemer weiterverarbeiten kann.
|
ChickenLipsRfun2eat
Supporter
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12070
|
Hallo! Wie dein Infrarot-Gerät heisst, weiss ich nicht, aber ich finde Tastaturen im System so:
1
2
3
4
5
6
7
8
9
10
11
12 | def detect_keyboard_event_numbers():
"""Loops through devices, returning all keyboards."""
keyboard_paths = []
with open("/proc/bus/input/devices") as file:
lines = file.readlines()
pattern = re.compile('H: Handlers=sysrq kbd event[0-9]|B: EV')
handlers = list(filter(pattern.search, lines))
for index, handler in enumerate(handlers):
if handler.startswith('H', 0) and handlers[1+index] == "B: EV=120013\n":
keyboard_paths += handler[27]
return keyboard_paths
|
Du kannst ja mal mit less /proc/bus/input/devices gucken, ob du deinen Infrarot-Empfänger identifizieren kannst. Die einzige Abhängigkeit der Funktion ist re für die Zeichenkettensuche. Das lässt sich sicherlich noch besser machen, aber es ist ein Ansatz 😉
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 10978
|
Mit pyudev (Paket python3-pyudev) könnte das z.B. so aussehen wenn man mit dem Device-Namen nach einem Kernel Input Device suchen will:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | #!/usr/bin/env python3
import pyudev
import sys
def get_device_path(devicename):
context = pyudev.Context()
for device in (d for d in context.list_devices(subsystem='input') if d.parent is not None):
if (name := device.parent.attributes.get('name')) and name.decode() == devicename:
return '/dev/input/' + device.sys_name
if __name__ == '__main__':
d_name = sys.argv[1]
print(get_device_path(d_name))
|
$ python3 udev_filter.py "Nuvoton w836x7hg Infrared Remote Transceiver"
/dev/input/input32
|
jms3000
(Themenstarter)
Anmeldungsdatum: 29. Januar 2015
Beiträge: 742
|
Ich suche eine allgemeingültige Lösung, die nicht von meiner Konfiguration abhängt. Ich vermute, dazu muss man über /sys/class/rc gehen.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 10978
|
Du kannst nach rc-core Geräten suchen, aber davon kann es mehr als eines geben (z.B. bringen viele TV-Karten eigene Empfänger mit):
1
2
3
4
5
6
7
8
9
10
11
12
13 | #!/usr/bin/env python3
import pyudev
def get_rc_core_paths():
context = pyudev.Context()
for device in (d for d in context.list_devices(subsystem="input") if d.parent is not None):
if (name := device.parent.attributes.get('name')) and 'rc/rc' in device.parent.sys_path:
yield "/dev/input/" + device.sys_name
if __name__ == "__main__":
for p in get_rc_core_paths():
print(p)
|
|
jms3000
(Themenstarter)
Anmeldungsdatum: 29. Januar 2015
Beiträge: 742
|
Wow, super, danke! So funktioniert es.
Schade nur dass man nicht direkt auf die Geräteklasse "rc" filtern kann (über "/sys/class/rc").
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 10978
|
jms3000 schrieb: Wow, super, danke! So funktioniert es.
Schade nur dass man nicht direkt auf die Geräteklasse "rc" filtern kann (über "/sys/class/rc").
Kann man auch machen:
| #!/usr/bin/env python3
from pathlib import Path
for p in Path("/sys/class/rc/").glob("rc*/input*/event*/"):
print(f"/dev/input/{p.name}")
|
|
jms3000
(Themenstarter)
Anmeldungsdatum: 29. Januar 2015
Beiträge: 742
|
Das sieht gut aus. Meinst du dieser Weg ist sauber?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 10978
|
Das hängt davon ab, was du vor hast - der Weg über pyudev hat den Vorteil, dass man sich über an- bzw. abgesteckte Geräte benachrichtigen lassen kann (vgl. https://pyudev.readthedocs.io/en/latest/guide.html#monitoring-devices) - wenn man das nicht braucht, kann man auch den Kernel-Device Tree direkt auslesen.
|
jms3000
(Themenstarter)
Anmeldungsdatum: 29. Januar 2015
Beiträge: 742
|
Ich möchte die IR-events lesen und an home assistant weiterleiten.
|