[Deprecated} Using the Flirc USB for remote control with mOde 5.4+ - TheOldPresbyope - 07-12-2019
[Update 20200928: The addition of triggerhappy in moOde 6.4.2 has made this Python approach unnecessary. See instead Using FLIRC and other USB input devices for remote control.]
[For the time being this is an on-going exploration. It will be converted to a proper HowTo when some odds-n-ends have been taken care of. This note assumes you are moderately Linux literate.]
The Flirc USB is an IR-to-USB adapter which "allows you to pair any remote control with your computer or media center. Just walk through our super simple cross platform pairing application, and you're done. Use your previously paired remote with no additional software on any machine with flirc" [quoting from the flirc.tv website].
Well, I didn't exactly find it super simple---there were some interesting bumps in the road---but I'm well along my way to a solution which allows me to control a number of moOde's playback functions from an IR-remote I had on hand (an older-model Roku IR-controller, as it happens, with 12 buttons).
I've implemented the usual play/pause, previous/next track, volume up/down, mute/unmute, load default playlist, load favorites playlist functions, and still have four buttons left over for functions I haven't thought about yet.
My approach differs from @didier31's FLIRC-USB for remote control in that I'm running a headless moOde installation without local display and wanted to avoid adding X-stuff I knew I didn't need. I chose to take advantage of a useful Python module instead. Candidly, I took this approach because I wanted to see if I could make it work and not because I thought there was anything wrong with his prior work. Courses for horses, as they say.
There's nothing special about my particular IR-remote and nothing special about the specific functions I chose to implement.
The Flirc presents to the operating system as a USB-keyboard input device. This makes life pretty simple---mostly.
Summary of steps:
- program the Flirc to output specific keycodes in response to button presses on the remote.
- write a Python script to react to events with these keycodes, invoking mpc or Tim's utility scripts.
- use systemd/udev to start the script when the Flirc is present at boot or hotplugged.
I've got 1) and 2) in hand and am working on a solution for 3) I can be happy with.
Some Details:
Nope, I'm not going to turn this into a travelogue of how I got from point A to point B by meandering through the forest. I'll put the gory details somewhere, maybe a personal blog, for those who care.
But I have to point out one detail. The Flirc documentation and software implies you can mix-and-match mimicking standard keyboard keys (like a-z), which they colorfully call "valid commands", and media-control keys (like play/pause). Well, yeah, you can but this turns out to involve two different USB endpoints, one for media-control and one for keyboard.
At this stage of the game I wanted to deal with only one endpoint, and there weren't enough media-control codes available from Flirc (or at least I could find no way to get to them) for my needs, so I programmed all my buttons to emit keyboard codes (KEY_A, KEY_B, KEY_C, etc.), as you'll see in the script below. No one but the script sees the actual values so it doesn't matter unless you intend to move the Flirc back and forth between moOde and some other computer or media control center which expects to receive actual media-control commands as defined in the USB spec.
The script itself is an anticlimax:
Code: pi@moode54b2:~ $ more Flirc-moode.py
#!/usr/bin/python3
import os, asyncio,evdev,subprocess,time
# Hackery by TheOldPresbyope
# - control some moOde playback functions from a Flirc USB
# the following endpoint tracks media keys:
#flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-event-if01')
# the following endpoint tracks "valid command" keys
flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-if01-event-kbd')
# make sure Raspbian doesn't consume the keyboard input before we do
flirc.grab()
# paired with my Roku remote to have the following outputs
# *** had to rework to use only "valid command" keys so could watch
# *** just one endpoint
#
# Roku button Flirc output moOde function
# "left arrow button" -> "KEY_A" => favorites
# "home button" -> "KEY_B" => default playlist
# "up angle button" -> "KEY_C" => volume up
# "left-angle bracket button" -> "KEY_D" => previous
# "OK button" -> "KEY_E" => mute/unmute
# "right angle bracket button" -> "KEY_F" => next
# "down angle button" -> "KEY_G" => volume down
# "redo button" -> "KEY_H" => nothing yet
# "asterisk button" -> "KEY_I" => nothing yet
# "double-left diamond button" -> "KEY_J" => nothing yet
### careful: flirc_util 3.22.4 says "k" is not a valid letter!!!
# "play/pause button" -> "KEY_L" => play/pause
# "double-right diamond button" -> "KEY_M" => nothing yet
for event in flirc.read_loop():
if event.type == evdev.ecodes.EV_KEY:
attrib = evdev.categorize(event)
if attrib.keystate == 1:
if attrib.keycode == 'KEY_F':
subprocess.run(['mpc','next'])
elif attrib.keycode == 'KEY_D':
subprocess.run(['mpc','prev'])
elif attrib.keycode == 'KEY_C':
subprocess.run(['/var/www/vol.sh','-up','10'])
elif attrib.keycode == 'KEY_G':
subprocess.run(['/var/www/vol.sh','-dn','10'])
elif attrib.keycode == 'KEY_L':
subprocess.run(['mpc','toggle'])
elif attrib.keycode == 'KEY_A':
subprocess.run(['mpc','clear'])
time.sleep(0.1)
subprocess.run(['mpc','load','Favorites'])
elif attrib.keycode == 'KEY_B':
subprocess.run(['mpc','clear'])
time.sleep(0.1)
subprocess.run(['mpc','load','Default Playlist'])
elif attrib.keycode == 'KEY_E':
subprocess.run(['/var/www/vol.sh','-mute'])
Easy peasy. As you can see, this is mostly a simple case statement, except Python doesn't have a case statement! There's alternatives to the cascading if/elif construction but they're too razzle-dazzle for me, at least at this stage. The ordering of the tests got scrambled because of my reworking from media-control keycodes. It doesn't matter programmatically but it looks odd and will get fixed before the HowTo appears. The script loops endlessly until you kill it explicitly, you unplug the Flirc, or you reboot moOde.
So, to try it out, you first need to program your Flirc on another host to generate the keycodes you want with the IR-remote you have (see flirc.tv for software and docs). If you choose a different scheme from mine you'll need to do your homework on the keycodes actually emitted (hint: they're not in the Flirc docs).
For moOde, you need Raspbian Buster for its up-to-date Python3 and evdev module. This means Tim's moOde 5.4b2 soon-to-be moOde 6.
Install evdev
Code: sudo apt-get install python3-evdev
Plug in the Flirc on your moOde player. Copy the script to somewhere convenient like pi's home directory, calling it what you want; change the key values to match your Flirc configration; and make the script executable (chmod +x) for convenience. Since I don't yet have a systemd/udev solution, you'll have to start the script manually or add it to moOde's startup activity (not recommended but if you never remove the Flirc this would work). For mine, this means:
Code: ./Flirc-moode.py
or
./Flirc-moode.py &
(where the script runs in the terminal in the first instance and persists in the background in the second)
Start pressing buttons and watch moOde responds. Note that you'll also start seeing the output from mpc commands since you've invoked the script from the command line. That'll go away with systemd/udev. You can play with redirecting output to the bit bucket if desired.
Final thought:
Almost exactly the same script works with my Satechi Bluetooth Multi-Media Remote. Unfortunately, the systemd/udev work is harder here because of the intermediary Bluetooth controller and because the Satechi goes to sleep after a period of inactivity. More to come.
Regards,
Kent
RE: Using the Flirc USB for remote control with mOde 5.4+ - DRONE7 - 12-15-2019
Hi Kent, I thought to give your How-to a try with my Flirc (original) usb device. Pi 3 running MoOde 6.4, Kali and Piano Dac.
Errors when running ./Flirc-moode.py
Code: ./Flirc-moode.py
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/evdev/device.py", line 125, in __init__
fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK)
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/by-id/usb-flirc.tv_flirc-if01-event-kbd'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "./Flirc-moode.py", line 10, in <module>
flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-if01-event-kbd')
File "/usr/lib/python3/dist-packages/evdev/device.py", line 127, in __init__
fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK)
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/by-id/usb-flirc.tv_flirc-if01-event-kbd'
Script used as per your details but modded for HP remote..
Code: #!/usr/bin/python3
import os, asyncio,evdev,subprocess,time
# Hackery by TheOldPresbyope
# - control some moOde playback functions from a Flirc USB
# the following endpoint tracks media keys:
#flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-event-if01')
# the following endpoint tracks "valid command" keys
flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-if01-event-kbd')
# make sure Raspbian doesn't consume the keyboard input before we do
flirc.grab()
# paired with my Roku remote to have the following outputs
# *** had to rework to use only "valid command" keys so could watch
# *** just one endpoint
#
# HP button Flirc output moOde function
# "Power button" -> "KEY_A" => Shutdown
# "Play button" -> "KEY_B" => Play
# "Pause button" -> "KEY_C" => Pause
# "Previous button" -> "KEY_D" => Previous
# "Next button" -> "KEY_E" => Next
# "Stop button" -> "KEY_F" => Stop
# "1 button" -> "KEY_G" => Radio 1
# "2 button" -> "KEY_H" => Radio 2
# "3 button" -> "KEY_I" => Radio 3
# "4 button" -> "KEY_J" => Radio 4
### careful: flirc_util 3.22.4 says "k" is not a valid letter!!!
# "5 button" -> "KEY_L" => Radio 5
# "6 button" -> "KEY_M" => Radio 6
# "7 button" -> "KEY_N" => Radio 7
# "8 button" -> "KEY_O" => Radio 8
# "9 button" -> "KEY_P" => Radio 9
# "0 button" -> "KEY_Q" => Radio 0
# "Mute button" -> "KEY_R" => Mute/Unmute
# "Win button" -> "KEY_S" => Toggle Play/Pause
# "RedTV button" -> "KEY_T" => Favourites
for event in flirc.read_loop():
if event.type == evdev.ecodes.EV_KEY:
attrib = evdev.categorize(event)
if attrib.keystate == 1:
if attrib.keycode == 'KEY_A':
subprocess.run(['mpc','shutdown'])
elif attrib.keycode == 'KEY_B':
subprocess.run(['mpc','play'])
elif attrib.keycode == 'KEY_C':
subprocess.run(['mpc','pause'])
elif attrib.keycode == 'KEY_D':
subprocess.run(['mpc','prev'])
elif attrib.keycode == 'KEY_E':
subprocess.run(['mpc','next'])
elif attrib.keycode == 'KEY_F':
subprocess.run(['mpc','stop'])
Code: $ lsusb
Bus 001 Device 004: ID 20a0:0001 Clay Logic
Anything jump out there ?
Cheers,
BoB
RE: Using the Flirc USB for remote control with mOde 5.4+ - TheOldPresbyope - 12-15-2019
@DRONE7
Hi, Bob.
Thinking this project was "done and dusted" I moved on to try some other types of remotes. ATM I've got an OSMC RF remote on my desk I want to poke at.
I'll need to revisit what I did with the FLIRC. IIRC I did a little detective work with Python to see how it was enumerated in the /dev tree and then just assumed it would always be the same. Maybe this assumption falls down with an "original" FLIRC (if that is different from mine) or with other input devices also connected.
What else do you have connected to your RPi?
Regards,
Kent
RE: Using the Flirc USB for remote control with mOde 5.4+ - TheOldPresbyope - 12-15-2019
(12-15-2019, 02:33 PM)TheOldPresbyope Wrote: @DRONE7
Hi, Bob.
Thinking this project was "done and dusted" I moved on to try some other types of remotes. ATM I've got an OSMC RF remote on my desk I want to poke at.
I'll need to revisit what I did with the FLIRC. IIRC I did a little detective work with Python to see how it was enumerated in the /dev tree and then just assumed it would always be the same. Maybe this assumption falls down with an "original" FLIRC (if that is different from mine) or with other input devices also connected.
What else do you have connected to your RPi?
Regards,
Kent
Done and dusted? I see some promises of more work in my orginal post. Some shiny new thing must have caught my eye back in July and I was off in another direction!
Anyway, our two FLIRCs have different USB ids: For mine it's "20a0:0006" and for yours it's "20a0:0001".
What do you see in /dev/input/by-id? I just spun up a fresh copy of moOde6.4.0 on an rPi3B+ and got
Code: pi@moode:~ $ lsusb
Bus 001 Device 004: ID 20a0:0006 Clay Logic
Bus 001 Device 005: ID 0424:7800 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
pi@moode:~ $ ls -l /dev/input/by-id
total 0
lrwxrwxrwx 1 root root 9 Nov 26 12:54 usb-flirc.tv_flirc-event-if01 -> ../event1
lrwxrwxrwx 1 root root 9 Nov 26 12:54 usb-flirc.tv_flirc-if01-event-kbd -> ../event0
I'm not sure it will help but you might also post the verbose lsusb output. Here's the beginning of the output for my particular device id
Code: pi@moode:~ $ sudo lsusb -v -d 20a0:0006
Bus 001 Device 004: ID 20a0:0006 Clay Logic
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x20a0 Clay Logic
idProduct 0x0006
bcdDevice 2.00
iManufacturer 1 flirc.tv
iProduct 2 flirc
iSerial 0
bNumConfigurations 1
...
Regards,
Kent
RE: Using the Flirc USB for remote control with mOde 5.4+ - DRONE7 - 12-15-2019
Rpi3-Kali-Piano Dac... nothing else connected.
Code: $ lsusb
Bus 001 Device 004: ID 20a0:0001 Clay Logic
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Code: ls -l /dev/input/by-id
total 0
lrwxrwxrwx 1 root root 9 Dec 15 20:38 usb-flirc.tv_flirc-event-if00 -> ../event1
lrwxrwxrwx 1 root root 9 Dec 15 20:38 usb-flirc.tv_flirc-event-kbd -> ../event0
Code: $ sudo lsusb -v -d 20a0:0001
Bus 001 Device 004: ID 20a0:0001 Clay Logic
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x20a0 Clay Logic
idProduct 0x0001
bcdDevice 1.00
iManufacturer 1 flirc.tv
iProduct 2 flirc
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0032
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0
bInterfaceProtocol 1 Keyboard
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.01
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 148
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 50
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 50
Device Status: 0x0000
(Bus Powered)
would it be as simple as changing usb-flirc.tv_flirc-event-if01 to usb-flirc.tv_flirc-event-if00 in the appropriate file..?
RE: Using the Flirc USB for remote control with mOde 5.4+ - TheOldPresbyope - 12-15-2019
Interesting.
Yup. In Flirc-moode.py, try changing
Code: # the following endpoint tracks media keys:
#flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-event-if01')
# the following endpoint tracks "valid command" keys
flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-if01-event-kbd')
to
Code: # the following endpoint tracks media keys:
#flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-event-if00')
# the following endpoint tracks "valid command" keys
flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-event-kbd')
Note I was using only the "valid command" keys, hence the script is using the kbd endpoint.
Regards,
Kent
RE: Using the Flirc USB for remote control with mOde 5.4+ - DRONE7 - 12-15-2019
Ok now I have...
Code: $ ls -l /dev/input/by-id
total 0
lrwxrwxrwx 1 root root 9 Dec 16 07:28 usb-flirc.tv_flirc-event-if00 -> ../event1
lrwxrwxrwx 1 root root 9 Dec 16 07:28 usb-flirc.tv_flirc-event-kbd -> ../event0
and after a reboot still throwing the same errors
Code: $ ./Flirc-moode.py
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/evdev/device.py", line 125, in __init__
fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK)
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/by-id/usb-flirc.tv_flirc-if00-event-kbd'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "./Flirc-moode.py", line 10, in <module>
flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-if00-event-kbd')
File "/usr/lib/python3/dist-packages/evdev/device.py", line 127, in __init__
fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK)
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/by-id/usb-flirc.tv_flirc-if00-event-kbd'
I'm now off to complete the building of a 'submarine' engine for a coffin.... so will check back tonight.
Cheers,
Bob.
RE: Using the Flirc USB for remote control with mOde 5.4+ - TheOldPresbyope - 12-15-2019
@DRONE7
Sorry, there's no '-if00-' in the kbd endpoint.
RE: Using the Flirc USB for remote control with mOde 5.4+ - DRONE7 - 12-15-2019
(12-15-2019, 06:45 PM)TheOldPresbyope Wrote: @DRONE7
Sorry, there's no '-if00-' in the kbd endpoint. Just had a break waiting for glue and paint to dry....and
Yes, removed '-if00-' and that got the Flirc V1 active and I'm getting output for some buttons. Progress !
Next break I will redo my mpc configs in ..
Thanks !!
RE: Using the Flirc USB for remote control with mOde 5.4+ - TheOldPresbyope - 12-15-2019
@DRONE7
Glad to hear you're making progress. I'm trying to understand USB better. ATM I'm trying to understand how names like "usb-flirc.tv_flirc-event-kbd" get generated from the low-level USB-descriptor information I see. I shouldn't have to cut-n-paste it into my script. Haven't a clue yet but maybe I just haven't read enough background material.
This will yield somewhat redundant information, but I'd appreciate you at some point sending me the output from
Code: sudo cat /sys/kernel/debug/usb/devices
Regards,
Kent
|