In the previous post on the topic of IR remote controls, I looked into
the possibility of using a Python script to read the event queue generated by
the Linux kernel. However most seem intent on using
the LIRC (Linux Infrared Remote Control) package. To
quote lirc.org "Using lirc on Raspberry Pie [sic] is quite
popular these days." While I style myself as a contrarian at times, it is
worthwhile examining what the majority is doing. Accordingly, I installed the
package on the Orange Pi Zero and managed to get simple demonstration
programs working with it. This is yet another example of writing about a
subject in order to try to understand it, and give that LIRC supports more IR remotes than the Linux kernel, this could be rather useful later on.
Again, while I was using an Orange Pi Zero running Armbian Stretch as a test bed, much of what follows would probably be valid for the Raspberry Pi.
Linux kernel then there is probably no need for LIRC or Python scripts and so on. Look at the sidebar
in my previous post.Table of Contents
- Installing LIRC
- Configuring LIRC
- IR Remote for Domoticz using
irexec - Python Bindings
- IR Remote for Domoticz using Python
- Conclusion
Installing the Kernel Module
By default the IR receiver driver, called sunxi-cir, is not
installed. The simplest method (actually the only one known to me) of
loading the kernel module when booting is to use the
armbian-config utility. Enable the cir module in
the System/Hardware settings. If you are not familiar with this
procedure, the details are in the previous post
in this series.
Installing LIRC
As I had already played with the IR module, I restored the OS to a pristine state:
- disabled all IR protocols
zero@opi:~$ echo lirc | sudo tee /sys/class/rc/rc0/protocols lirc zero@opi:~$ cat /sys/class/rc/rc0/protocols rc-5 nec rc-6 jvc sony rc-5-sz sanyo sharp mce_kbd xmp imon [lirc]
- commented out the
crontask on rebooting that enabled thenecprotocolzero@opi:~$ crontab -eAnd then added the#in front of the line#@reboot echo nec | sudo tee /sys/class/rc/rc0/protocols
Of course these two steps are not necessary if nothing had been done with the IR module beforehand.
Next, I checked that lirc was not installed.
Installation of the lirc package is done in the usual way as
it is available in the Armbian Stretch
depository. The status of the service should be checked after.
The lircd-uinput.service failed. For what follows that
does not matter. Should I decide to use lirc, then I will
investigate this situation probably looking at modifying the unit file not to
load that service. At the moment, I do not see the need for
lircmd.service and would opt not to load it either.
Configuring LIRC
The documentation at lirc.org is thorough but as
it is often the case when broaching a new subject, I found it a bit
overwhelming. The short post on codelectron How to setup Infrared Remote Control in Orange pi Zero using
lircd and python, dated May 25, 2017, was a good starting point even if
already outdated.
There are three configuration files to contend with, two of which have to
be created. The third, the lirc driver configuration file, needs
to be modified. With version 0.9.4 of lirc that file is called
lirc_options.conf. Unfortunately, there is much outdated
information on the Web containing instructions about
hardware.conf which was the former name of the driver
configuration file. The format of the file is now different and there is no
point in creating a hardware.conf file, it will not be read by
the lirc driver. Fortunately, not much needs to be done to the
lirc_options.conf file.
Two entries, driver=devinput and device=auto,
in the [lircd] section need to be changed.
Restart the lirc services and check on the status of the
services.
At this point it is possible to test that the lirc driver is
working. Stop the lircd daemon and use the mode2
utility, included in the lirc package, to read more
or less raw data from the IR remote.
It is not necessary to specify the device, mode2
alone would work here. The output are time values and mode2 is
showing the train of infrared pulses from the IR remote. Think of it as a
software oscilloscope as the documentation suggests. Indeed try running the command
with the -s "scope" option:
The lirc main configuration file must be created. It
should contain the required definition of the IR remote which will be used by
lirc to convert IR pulses into codes. In principle, it can be
generated with the irrecord utility. However, I could not get it
to work with my cheap IR remote and the comprehensive LIRC
Remotes Database did not contain a definition for my remote. Fortunately,
Uncle Scrooge created a working configuration file in early 2014. Here is its content
with additional comments giving the reference.
Download keyes.lircd.conf.
I saved the file as keyes.lircd.conf in the user home
directory. The next step consists of copying the configuration file to its
proper location as shown below. The lircd service will
automatically load any configuration file in the destination directory, as
long as the file name ends with .lircd.conf.
Testing will be done according to the instructions in the LIRC configuration guide. First
make sure that lircd.socket is running and then
stop the lircd daemon if it happens to be running.
Restart that service manually so that its messages will be visible.
As can be seen, the IR remote configuration file
keyes.lircd.conf has been loaded. Start a new terminal on the
desktop and open another SSH session with the Orange Pi Zero. The
irw utility, also included in the LIRC package, can then be used
to read from the lircd socket.
Once irw connects with the socket, lircd
will show that it has a new client.
Press some buttons on the IR remote and irw should display the
corresponding decoded key symbols as shown below.
Quit irw by pressing the CtrlC
combination. At that point lircd should say that the client has
been disconnected.
Stop lircd by pressing the CtrlC combination.
There is yet one more configuration file to set up as will be seen in the following section.
In addition to the Uncle Scrooge post about the Keyes remote, I found a couple of blogs worth a mention. Keyes IR Remote Sensor (2014) at Feiticeir0's Blog and Arduino Xinda / Keyes Infrared Remote Tutorial (2016) at Henry's Bench both show how to find the codes with an Arduino using the IRremote.h library using the same remote as I have. Also of interest is a discussion about the Keyes remote on the Arduino forum.
Python Bindings
There are a number of Python packages that can be used as clients with
lircd. The oldest appears to be pyLIRC by Linus McCabe. It is
no longer maintained by the author but it remains available on SourceForge.
Development has been taken up by Paul Hummer which renamed the project pyLirc2. This
version is available from the Armbian Strecth
repository.
This is a Python 2 package. I created the following lircc type
configuration file that I saved in the home directory under the name
pylirc.conf. It is basically the same as the one created by the
original package author.
Download the complete pylirc.conf file.
This is an example of an "application-specific [...] configuration file"
that "provides a way to translate the application-agnostic events which lircd
makes available on /usr/var/run/lirc/lircd to application-specific strings"
(source).
To be a bit less cryptic, this file maps key code such as KEY_DOWN
to a string down which has meaning for an application.
In the example, three parameters are defined in each entry.
- button:
- The key code returned by
lircdas defined in a remote configuration file,keyes.lircd.confin this case. - config:
- The string that will be passed on to the program connected to the
lircdsocket. - prog:
- The name of the program that should receive the
configstring. When an application connects withlircdas a client, it provides a name and it will receive those button events that have the same name in theprogfield. Think of the mandatoryprogparameter as a port when using a TCP socket. That "alphabetic port" does not have to be the name of the client program. It can be any word, although it will hopefully be unique, as many clients can be connected tolircd.
Other parameters could be included. While I saved the file as
pylirc.conf in the user home directory for test purposes, its
default name and location is .lircrc in the user home
directory.
To test, I slightly modified one of the sample scripts written by the original author.
Download the script pylirc_test.py.
The two major functions in the script are:
- integer = pylirc.init(string name[, string configuration [, integer blocking ]])
- returns: 0 on failure else a socket id as returned by
lirc_init().name: must be the same asprogentry in thelircconfiguration file entries.configuration: the name of thelircconfiguration file (by default~./lircrc).blocking: 1 for blocking mode, 0 for nonblockling mode.- list = pylirc.nextcode([integer Extended])
- returns: all commands in the event queue as a list.
Extended: 0 - elements in the list are strings, 1 - elements in the result list are dictionaries.
There is more information here. Here is the output of the program as I pressed on various buttons on the IR remote.
It is not too hard to install pyLirc2 (or a.k.a.
python-pylirc) in Python 3. Follow the
instructions by project-owner. They work! Furthermore
the pylirc_test.py also works with Python 3.
The other binding often mentioned is python-pylirc by
Thomas Preston. Unfortunately, I could not install the library as instructed
on the github home page.
Of course before that attempt, I had to install the pip3, to
no purpose as can be seen. It was possible to install the Python 2
version.
Trying the same thing with the Python 3 package did not work. Although
the installation process seemed to work, for some reason lirc
could not be imported.
I tested the Python 2 version of python-lirc, in an
interactive Python session, with the same application configuration file as
before pylirc.conf.
As can be seen, the functions lirc.init and
lirc.nextcode() are quite similar to those in
pyLirc2. There are differences in default behaviour. I have not
looked into the details to comment any further.
LIRC.org has documentation about Python client bindings. I did not investigate after reading that they were "unstable python interfaces to read and send lirc data".
IR Remote for Domoticz
It is not difficult to modify the example file to implement a simple minded IR interface for IoT devices through Domotic.
Download the Python 2.7 script pylirc_domo.py.
Pressing the 1 button on the IR remote toggles the lamp by the bookshelves on or off, while pressing the 2 button on does the same with the sofa lamp.
This is a simple-minded script that assumes that the remote has one button for every home automation device to be controlled. Nevertheless, it does show that it is possible to use the LIRC package with a Python client as another means of controlling devices.
IR Remote for Domoticz using irexec
If nothing more complicated than using individual IR remote buttons to
toggle a light fixture through Domoticz is needed,
then there is no need to use a Python script. The lirc package
includes a client, irexec, that can execute shell commands. All
that needs to be done is to modify the application lircd
configuration file so that the config parameter is set to the
command to be executed and the prog parameter is set to
irexec. Here is an example. Note the different default location
of the lircrc configuration file: ~/.config/lircrc.
Download the complete lircrc configuration file.
This is an experiment in three different ways of toggling the state of two devices. The (1), (3) and (5) buttons on the IR remote toggle on or off a lamp with Domoticz device idx of 52. Buttons (2), (4) and (6) do the same but for the IoT device with an idx of 72. Buttons (1) and (2) are the most "verbose". They spit out information on the terminal, including the reply from Domoticz as shown below.
This is useful for debugging, but not so much when the Orange Pi Zero
is used as a headless server and irexec will be launched
as a service (daemon).
Buttons (3) and (4) are completely silent. It quickly becomes obvious that there is a problem when using those, especially with a cheap remote. There is no positive feedback that the IR code was ever sent.
Buttons (5) and (6) provide a possible solution. The red status LED on the Orange Pi Zero, which is normally off, is turned on at the beginning of the command and turned off at the end. The visual feedback is comforting. I noticed that my box set has a similar arrangement. It remains to be seen if that LED will be visible once the Orange Pi Zero is ensconced in its tiny case.
Those are very long command strings, in practice I would replace them with a bash script that would take an integer, equal to the idx of the device to be controlled, as a command line parameter. Perhaps I would have more than one script to handle scenes as well as devices or else one script with two parameters.
Should I decide to implement this approach, I will write up the details.
Conclusion
If the task to be performed with an IR remote is stateless and if there
is a lircd definition file for the remote, then clearly the
easiest route to implementation is the combination of the lircd
and irexec services. By a stateless task, I mean that each
button press is translated into a bash command which is independent of
previous button presses and executed commands. Don't forget that the bash
command executed by irexec can be composed of numerous
commands joined with the control operators && and || or it could be a
bash script. In other words, the task performed in response to a button press
can be complex.
Unfortunately, I have had no success using irrecord to
create a valid lircd definition file for three "unknown" IR
remotes that are lying about. I have yet to look into using the IRremote
package with an Arduino for that purpose. And there is an Java based GUI
application; IrScrutinizer by Bengt Martensson, that
I could perhaps install on my desktop computer; I have a USB IR receiver
somewhere. The author has documented the project here IrScrutinizer
documentation at HARCToolbox, and here IrScrutinizer Guide at JP1.
If a Python script (or something else capable of reading a
Linux event queue) is going to be used and if the IR protocol of
the remote is supported by the Linux kernel then there is no
need for LIRC. The trade-off is that a much more
complex script will have to be written.
And a reminder that to control a program like Kodi there may be no need
for LIRC or Python scripts and so on. Look into using
ir-keytable. My previous post
shows how to test if the remote could be used in this fashion.