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
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.
Linuxkernel 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
- Python Bindings
- IR Remote for Domoticz using Python
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.
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 the
necprotocolzero@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.
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.
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
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
lirc driver. Fortunately, not much needs to be done to the
[lircd] section need to be changed.
lirc services and check on the status of the
At this point it is possible to test that the
lirc driver is
working. Stop the
lircd daemon and use the
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
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:
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.
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
Testing will be done according to the instructions in the LIRC configuration guide. First
make sure that
lircd.socket is running and then
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
irw connects with the socket,
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.
irw by pressing the CtrlC
combination. At that point
lircd should say that the client has
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.
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
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
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"
To be a bit less cryptic, this file maps key code such as
to a string
down which has meaning for an application.
In the example, three parameters are defined in each entry.
- The key code returned by
lircdas defined in a remote configuration file,
keyes.lircd.confin this case.
- The string that will be passed on to the program connected to the
- The name of the program that should receive the
configstring. When an application connects with
lircdas a client, it provides a name and it will receive those button events that have the same name in the
progfield. Think of the mandatory
progparameter 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 to
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
To test, I slightly modified one of the sample scripts written by the original author.
Download the script
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
name: must be the same as
progentry in the
lircconfiguration file entries.
configuration: the name of the
lircconfiguration file (by default
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
pylirc_test.py also works with Python 3.
The other binding often mentioned is
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
no purpose as can be seen. It was possible to install the Python 2
Trying the same thing with the Python 3 package did not work. Although
the installation process seemed to work, for some reason
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
As can be seen, the functions
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".
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.
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
includes a client,
irexec, that can execute shell commands. All
that needs to be done is to modify the application
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:
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.
If the task to be performed with an IR remote is stateless and if there
lircd definition file for the remote, then clearly the
easiest route to implementation is the combination of the
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
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.