Den Music Player Daemon (mpd) per Fernbedienung steuern (Teil1)

Das folgende, aus mehreren Teilen bestehende Tutorial, dreht sich um die Frage, wie der Raspberry Pi (RPi) per Fernbedienung gesteuert werden kann. Genauer gesagt, soll das Abspielen von einfachen Internet Radio Streams über den Music Player Daemon (mpd) mit Hilfe der Fernbedienung beeinflusst werden können. Dazu habe ich ein kleines Kontrollprogramm (in C++) geschrieben, welches auf dem RPi läuft, die Eingaben der Fernbedienung entgegennimmt und entsprechend den mpd Anweisungen gibt.

In den ersten Teilen des Tutorials verwende ich entweder Pseudocode oder entsprechende Diagramme, der Programmcode wird dagegen erst am Schluss analysiert.

Bitte entschuldigt, wenn dieser Post noch nicht so professionell aussieht, wie ihr es vielleicht gewohnt seid. Dies ist meiner erster Post und ich muss mich erst einmal in WordPress einarbeiten. Es kann nur besser werden…

Die Fernbedienung

Als erster Punkt war mir wichtig, dass die Fernbedienung auf keine direkte Sichtverbindung zu dem RPi angewiesen ist. Denn ich wollte, dass weder der RPi noch ein Empfängersensor sichtbar ist. Somit fielen schon mal alle Infrarot-Fernbedienungen weg.

Der zweite Punkt war der Preis, aber auch die Anzahl der Bedienelemente. Denn mehr als die Sender wechseln und den Player zu aktivieren oder deaktivieren, war nicht notwendig. Auch wollte ich weder ein Android-Gerät, Iphone, Ipad, usw. verwenden, weil die Bedienung so einfach wie möglich sein sollte, unabhängig von irgendwelchen Apps.

Nach einiger Suche habe ich mich für eine „Targus Presenter AMP18EU“ Fernbedienung entschieden, welche in Präsentationen benutzt wird, um zwischen Folien wechseln zu können. Diese hat drei Tasten: zwei zum wechseln der Folie und eine Taste zum Ein- und Ausschalten der Fernbedienung. Auch ist der Preis mit knapp 25,- EUR akzeptabel und die Fernbedienung ist auf den gängigen Einkaufsportalen im Internet verfügbar.

Die Fernbedienung wird mit dem RPi über einen USB-Dongle verbunden. Der USB-Dongle registriert sich als mehrere USB-Geräte, welcher unter /dev/input/.. abgefragt werden können. Um herauszufinden, über welchen Pfad tatsächlich die Fernbedienung abgefragt werden kann, habe ich die Programme ‚lsinput‘ und ‚input-events‘ aus dem Package ‚input-utils‘ verwendet (die folgenden Kommandos mit vorangestellten $ werden in der Kommandozeile ausgeführt):

Das Package wird (wenn nicht schon vorhanden) wie folgt installiert:

$ sudo apt-get install input-utils

Nach der Installation wird das Program lsinput aufgerufen, um herauszufinden, welche Eingabegeräte unter /dev/input registriert sind…

$ lsinput

… und erhält zum Beispiel folgende Ausgabe (Auszug):

..
/dev/input/event2
bustype : BUS_USB
vendor : 0x1048
product : 0x7d4
version : 273
name : "Targus Presentation Remote"
phys : "usb-bcm2708_usb-1.3/input2"
uniq : ""
bits ev : EV_SYN EV_KEY EV_REL EV_ABS EV_MSC EV_REP
..

Auf meinem RPi hat sich der Targus USB-Dongle also unter anderen auf /dev/input/event2 registriert. In der Ausgabe können wir sehen, dass in den Event-Bits das EV_KEY und EV_RELBit gesetzt ist. Damit können wir einerseits das Drücken (EV_KEY), als auch das Loslassen (EV_REL) der Tasten auslesen.

Weil aber mehrere Geräte mit dem Namen „Targus Presentation Remote“ registriert sind (hier sind es drei), müssen wir im nächsten Schritt den Gerätepfad ermitteln, über den wir die Tasten letztendlich auslesen können.

Dies geschieht über das Durchprobieren der per lsinput aufgelisteten Geräte. Dabei wird die Nummer des Gerätes z.B. /dev/input/event2 = 2 dem Programm input-events übergeben. Das Programm öffnet ein Gerät auf dem entsprechenden /dev/input/-Pfad und wartet einige Sekunden auf Eingaben des Gerätes. Können wir nach dem Drücken der Tasten auf der Fernbedienung entsprechende Event-Logging sehen, so haben wir das richtige Gerät gefunden. Beispielhaft folgt die Ausgabe des Gerätes 2, nach dem Start von input-events:

$ input-events 2
/dev/input/event2
bustype : BUS_USB
vendor : 0x1048
product : 0x7d4
version : 273
name : "Targus Presentation Remote"
phys : "usb-bcm2708_usb-1.3/input2"
uniq : ""
bits ev : EV_SYN EV_KEY EV_REL EV_ABS EV_MSC EV_REP
waiting for events
...
10:09:53.310608: EV_MSC MSC_SCAN 458830
10:09:53.310632: EV_KEY KEY_PAGEDOWN (0x6d) pressed
10:09:53.310639: EV_SYN code=0 value=0
...

Einlesen der Tasten in C++
Um die Tasten der Fernbedienung per C++-Programm einlesen zu können, genügt es, die Datei auf dem entsprechenden Pfad zu öffnen und aus dieser zu lesen. Der Programmcode sind dann beispielhaft wie folgt aus:

1. Gerät öffnen

std::string deviceName = "/dev/input/event2";
int deviceFd = open(deviceName, O_RDONLY);
if (deviceFd == -1) {
  // Fataler Fehler
}

2. Gerät initialisieren

fd_set set;
FD_ZERO(&set);
FD_SET(deviceFd, &set);
ret = select(deviceFd + 1, &set, NULL, NULL, NULL);
if (ret == -1) {
  // Fataler Fehler
}

3. Nach dem Öffnen und der Initialisierung des Gerätes kann dieses nun ausgelesen werden:

if (FD_ISSET(deviceFd, &set)) {
ret = read(deviceFd, &event, sizeof (event));
if (ret == -1) {
  // Fehler: vom Gerät kann nicht gelesen werden
} else if (ret == 0) {
  // Fehler: EOF erreicht
}
switch (event.type) {
  case EV_KEY:
    // event.code = Keycode der Taste
    // wenn event.value = 0, dann Taste losgelassen, sonst Taste gedrückt
  break;
}
...

Wie in dem Codesnippet zu sehen ist, wird der Code der gedrückten Taste in event.code gespeichert. Ob die Taste losgelassen oder gedrückte wurde, kann in event.value erkannt werden.

Im zweiten Teil werde ich auf die Steuerung des mpd über TCP eingehen.

Links zum Thema

Advertisements

I'm an independent german IT consultant for Java, J2E and C++ - in my spare time I work on embedded devices, digital Image- and Signal processing, riding motorcycle, doing sports and do many other things.

Tagged with: , , , , , , ,
Veröffentlicht in Raspberry Pi

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: