md
LIRC on the Orange Pi Zero
February 5, 2019
<-Using Bare Metal IR on the Orange Pi Zero ir-keytable on the Orange Pi Zero->

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.

If you ended up here because you want to control a program like Kodi with an IR remote and if is uses an IR protocol that is supported by the 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

  1. Installing the Kernel Module
  2. Installing LIRC
  3. Configuring LIRC
  4. Python Bindings
  5. IR Remote for Domoticz using Python
  6. IR Remote for Domoticz using irexec
  7. Conclusion

Installing the Kernel Module toc

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 toc

As I had already played with the IR module, I restored the OS to a pristine state:

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.

zero@opi:~$ sudo apt-cache policy lirc* lirc-compat-remotes: Installed: (none) Candidate: 0.9.0-1 Version table: 0.9.0-1 500 500 http://httpredir.debian.org/debian stretch/main armhf Packages lirc: Installed: (none) Candidate: 0.9.4c-9 Version table: 0.9.4c-9 500 500 http://httpredir.debian.org/debian stretch/main armhf Packages ...

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.

zero@opi:~$ sudo apt install -y lirc Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: libftdi1-2 libjack-jackd2-0 liblirc-client0 liblirc0 libopus0 libportaudio2 libusb-0.1-4 Suggested packages: jackd2 opus-tools lirc-compat-remotes lirc-drv-irman lirc-doc lirc-x setserial ir-keytable Recommended packages: python3-yaml gir1.2-vte The following NEW packages will be installed: libftdi1-2 libjack-jackd2-0 liblirc-client0 liblirc0 libopus0 libportaudio2 libusb-0.1-4 lirc 0 upgraded, 8 newly installed, 0 to remove and 0 not upgraded. Need to get 1,098 kB of archives. After this operation, 3,419 kB of additional disk space will be used. ... Processing triggers for systemd (232-25+deb9u8) ... zero@opi:~$ sudo systemctl status lirc* ● lircd.service - Flexible IR remote input/output application support Loaded: loaded (/lib/systemd/system/lircd.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2019-02-03 18:42:08 AST; 52s ago Docs: man:lircd(8) http://lirc.org/html/configure.html Main PID: 5404 (lircd) CGroup: /system.slice/lircd.service └─5404 /usr/sbin/lircd --nodaemon ... ● lircd.socket Loaded: loaded (/lib/systemd/system/lircd.socket; enabled; vendor preset: ena Active: active (running) since Mon 2019-02-04 14:24:02 AST; 1h 36min ago Listen: /run/lirc/lircd (Stream) ... ● lircmd.service - Convert IR remotes button presses to mouse movements and clicks Loaded: loaded (/lib/systemd/system/lircmd.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2019-02-03 18:42:10 AST; 50s ago Docs: man:lircmd(8) http://lirc.org/html/configure.html Main PID: 5437 (lircmd) CGroup: /system.slice/lircmd.service └─5437 /usr/sbin/lircmd --nodaemon ... ● lircd-uinput.service - Forward LIRC button presses as uinput events Loaded: loaded (/lib/systemd/system/lircd-uinput.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Sun 2019-02-03 18:42:14 AST; 46s ago Docs: man:lircd-uinput(8) http://lirc.org/html/configure.html Main PID: 5494 (code=exited, status=1/FAILURE) Feb 03 18:42:14 opi systemd[1]: Started Forward LIRC button presses as uinput events. Feb 03 18:42:14 opi lircd-uinput[5494]: lircd-0.9.4c[5494]: Info: lircd-uinput: Opening log, level: Info Feb 03 18:42:14 opi lircd-uinput[5494]: lircd-0.9.4c[5494]: Info: Reading data from /var/run/lirc/lircd, writing to /dev/uinput Feb 03 18:42:14 opi lircd-uinput[5494]: lircd-0.9.4c[5494]: Info: Using "_UP" as release suffix Feb 03 18:42:14 opi lircd-uinput[5494]: lircd-0.9.4c[5494]: Cannot open uinput device: /dev/uinput: No such file or directory Feb 03 18:42:14 opi lircd-uinput[5494]: lircd-0.9.4c[5494]: Error: Cannot setup uinput output file descriptor. Feb 03 18:42:14 opi systemd[1]: lircd-uinput.service: Main process exited, code=exited, status=1/FAILURE Feb 03 18:42:14 opi systemd[1]: lircd-uinput.service: Unit entered failed state. Feb 03 18:42:14 opi systemd[1]: lircd-uinput.service: Failed with result 'exit-code'.

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 toc

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.

zero@opi:~$ sudo nano /etc/lirc/lirc_options.conf

Two entries, driver=devinput and device=auto, in the [lircd] section need to be changed.

[lircd] nodaemon = False driver = default device = /dev/lirc0

Restart the lirc services and check on the status of the services.

zero@opi:~$ sudo systemctl restart lirc* zero@opi:~$ sudo systemctl status lirc* zero@opi:~$ sudo systemctl status lirc* ● lircd.service - Flexible IR remote input/output application support Loaded: loaded (/lib/systemd/system/lircd.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2019-02-03 19:12:07 AST; 2min 11s ago Docs: man:lircd(8) http://lirc.org/html/configure.html Main PID: 730 (lircd) Tasks: 1 (limit: 4915) CGroup: /system.slice/lircd.service └─730 /usr/sbin/lircd --nodaemon ... ● lircd.socket Loaded: loaded (/lib/systemd/system/lircd.socket; enabled; vendor preset: enabled) Active: active (running) since Sun 2019-02-03 19:12:05 AST; 2min 13s ago Listen: /run/lirc/lircd (Stream) ... ● lircmd.service - Convert IR remotes button presses to mouse movements and clicks Loaded: loaded (/lib/systemd/system/lircmd.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2019-02-03 19:12:06 AST; 2min 13s ago Docs: man:lircmd(8) http://lirc.org/html/configure.html Main PID: 600 (lircmd) Tasks: 1 (limit: 4915) CGroup: /system.slice/lircmd.service └─600 /usr/sbin/lircmd --nodaemon .... ● lircd-uinput.service - Forward LIRC button presses as uinput events Loaded: loaded (/lib/systemd/system/lircd-uinput.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Sun 2019-02-03 19:12:08 AST; 2min 11s ago Docs: man:lircd-uinput(8) http://lirc.org/html/configure.html Process: 734 ExecStart=/usr/sbin/lircd-uinput (code=exited, status=1/FAILURE) Main PID: 734 (code=exited, status=1/FAILURE)

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.

zero@opi:~$ sudo systemctl stop lircd Warning: Stopping lircd.service, but it can still be activated by: lircd.socket zero@opi:~$ mode2 -d /dev/lirc0 Using driver default on device /dev/lirc0 Trying device: /dev/lirc0 Using device: /dev/lirc0 pulse 9088 space 4448 pulse 624 space 536 pulse 624 ... ^C to exit

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:

zero@opi:~$ mode2 -s 30 Using driver default on device /dev/lirc0 Trying device: /dev/lirc0 Using device: /dev/lirc0 _ _------------____________------------____________------------____________

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.

# Please make this file available to others # by sending it to # # this config file was automatically generated # using lirc-0.9.0-pre1(default) on Sun Jan 19 10:13:19 2014 # # contributed by # # brand: KEYES # model no. of remote control: # devices being controlled by this remote: # # source: # Uncle Scrooge (19 January, 2014) Raspberry Pi and IR remote control with LIRC # https://pmitev.blogspot.com/2014/01/raspberry-pi-and-ir-remote-control-with.html begin remote name KEYES bits 16 flags SPACE_ENC|CONST_LENGTH eps 30 aeps 100 header 9281 4484 one 622 1657 zero 622 513 ptrail 622 repeat 9241 2236 pre_data_bits 16 pre_data 0xFF gap 109259 toggle_bit_mask 0x0 begin codes KEY_UP 0x629D KEY_DOWN 0xA857 KEY_LEFT 0x22DD KEY_RIGHT 0xC23D KEY_OK 0x02FD KEY_1 0x6897 KEY_2 0x9867 KEY_3 0xB04F KEY_4 0x30CF KEY_5 0x18E7 KEY_6 0x7A85 KEY_7 0x10EF KEY_8 0x38C7 KEY_9 0x5AA5 KEY_0 0x4AB5 KEY_NUMERIC_STAR 0x42BD KEY_NUMERIC_POUND 0x52AD end codes end remote

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.

zero@opi:~$ sudo cp keyes.lircd.conf /etc/lirc/lircd.conf.d

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.

zero@opi:~$ sudo systemctl start lircd.socket zero@opi:~$ sudo systemctl stop lircd Warning: Stopping lircd.service, but it can still be activated by: lircd.socket zero@opi:~$ sudo lircd --nodaemon --device /dev/lirc0 --driver default lircd-0.9.4c[2254]: Info: lircd: Opening log, level: Info lircd-0.9.4c[2254]: Warning: Running as root lircd-0.9.4c[2254]: Info: Using remote: KEYES. lircd-0.9.4c[2254]: Notice: lircd(default) ready, using /var/run/lirc/lircd

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.

zero@opi:~$ irw

Once irw connects with the socket, lircd will show that it has a new client.

lircd-0.9.4c[2254]: Notice: accepted new client on /var/run/lirc/lircd lircd-0.9.4c[2254]: Info: [lirc] protocol is enabled

Press some buttons on the IR remote and irw should display the corresponding decoded key symbols as shown below.

zero@opi:~$ irw 0000000000ff18e7 00 KEY_5 KEYES 0000000000ff18e7 01 KEY_5 KEYES 0000000000ff18e7 02 KEY_5 KEYES 0000000000ff5aa5 00 KEY_9 KEYES 0000000000ff5aa5 01 KEY_9 KEYES 0000000000ff5aa5 02 KEY_9 KEYES 0000000000ff6897 00 KEY_1 KEYES 0000000000ff6897 01 KEY_1 KEYES 0000000000ff6897 02 KEY_1 KEYES 0000000000ff02fd 00 KEY_OK KEYES 0000000000ff02fd 01 KEY_OK KEYES 0000000000ff02fd 02 KEY_OK KEYES 0000000000ff629d 00 KEY_UP KEYES 0000000000ff629d 01 KEY_UP KEYES 0000000000ff22dd 00 KEY_LEFT KEYES 0000000000ff22dd 01 KEY_LEFT KEYES ^C

Quit irw by pressing the CtrlC combination. At that point lircd should say that the client has been disconnected.

lircd-0.9.4c[2254]: Info: removed client ^C

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 toc

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.

zero@opi:/$ sudo apt install python-pylirc ... Unpacking python-pylirc (0.0.5-3+b1) ... Setting up python-pylirc (0.0.5-3+b1) ...

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.

zero@opi:~$ cat pylirc.conf begin button = KEY_UP prog = pylirc config = up end begin button = KEY_DOWN prog = pylirc config = down end begin button = KEY_NUMERIC_POUND prog = pylirc config = #, pound key end begin button = KEY_NUMERIC_STAR prog = pylirc config = the, key, is, a, star end begin button = KEY_0 prog = pylirc config = 0 end ...

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 lircd as defined in a remote configuration file, keyes.lircd.conf in this case.
config:
The string that will be passed on to the program connected to the lircd socket.
prog:
The name of the program that should receive the config string. When an application connects with lircd as a client, it provides a name and it will receive those button events that have the same name in the prog field. Think of the mandatory prog parameter 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 lircd.

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.

# !/usr/bin/python or !/usr/bin/python3 # # pyLirc, lirc (remote control) module for python # Copyright (C) 2003 Linus McCabe <pylirc.linus@mccabe.nu> # # Revision 1.7 2003/02/22 22:12:40 mccabe # Testprogram to test pylirc in multiple threads # # Revision 1.6 2002/12/21 20:30:26 mccabe # Added id and log entries to most files # import pylirc, time blocking = 1; # set to 0 for non-blocking operation if(pylirc.init("pylirc", "pylirc.conf", blocking)): code = {"config" : ""} while(code["config"] != "quit"): # Very intuitive indeed if(not blocking): print(".") # Delay... time.sleep(1) # Read next code s = pylirc.nextcode(1) # Loop as long as there are more on the queue # (dont want to wait a second if the user pressed many buttons...) while(s): # Print all the configs... for (code) in s: print("Command: %s, Repeat: %d" % (code["config"], code["repeat"])) if(code["config"] == "blocking"): blocking = 1 pylirc.blocking(1) elif(code["config"] == "nonblocking"): blocking = 0 pylirc.blocking(0) # Read next code? if(not blocking): s = pylirc.nextcode(1) else: s = [] # Clean up lirc pylirc.exit()

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 as prog entry in the lirc configuration file entries.
  • configuration: the name of the lirc configuration 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.

zero@opi:~$ python pylirc_test.py Command: up, Repeat: 0 Command: 1, Repeat: 0 Command: 2, Repeat: 0 Command: the, key, is, a, star, Repeat: 0 Command: #, pound key, Repeat: 0 Command: nonblocking, Repeat: 0 . . . . Command: blocking, Repeat: 0 Command: 0, Repeat: 0 Command: quit, Repeat: 0

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.

zero@opi:~$ python3 pylirc_test.py

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.

zero@opi:~$ pip3 install python3-lirc Collecting python3-lirc Could not find a version that satisfies the requirement python3-lirc (from versions: ) No matching distribution found for python3-lirc

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.

zero@opi:~$ wget https://github.com/tompreston/python-lirc/releases/download/v1.2.1/python-lirc_1.2.1-1_armhf.deb ... 2019-02-03 20:12:11 (378 KB/s) - ‘python-lirc_1.2.1-1_armhf.deb’ saved [26830/26830] zero@opi:~$ sudo dpkg -i python-lirc_1.2.1-1_armhf.deb Selecting previously unselected package python-lirc. (Reading database ... 34332 files and directories currently installed.) Preparing to unpack python-lirc_1.2.1-1_armhf.deb ... Unpacking python-lirc (1.2.1-1) ... Setting up python-lirc (1.2.1-1) ...

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.

zero@opi:~$ python Python 2.7.13 (default, Sep 26 2018, 18:42:22) [GCC 6.3.0 20170516] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import lirc >>> sockid = lirc.init("pylirc", "/home/zero/pylirc.conf") >>> while True: ... ircode = lirc.nextcode() ... if ircode != []: ... print ircode ... [u'down'] [u'down'] [u'down'] [u'up'] ^C

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 toc

It is not difficult to modify the example file to implement a simple minded IR interface for IoT devices through Domotic.

#!/usr/bin/python # coding: utf-8 # # pylirc_domo.py # # Python 2.7 script to convert IR codes to http command to # toggle lamps on or off with Domoticz # # Does not work in Python 3. # # Based on pylirc_test.py by Linus McCabe # http://pylirc.mccabe.nu/ # # 2019/02/04 21:30 Michel Deslierres # import pylirc import time import urllib blocking = 0; # set to 0 for non-blocking operation url_json = "http://192.168.1.22:8080/json.htm?type=command&param=switchlight&idx=" toggle_json = "&switchcmd=Toggle" lampe_biblio = 5 lampe_sofa = 6 if(pylirc.init("pylirc", "pylirc.conf", blocking)): code = {"config" : ""} while(code["config"] != "quit"): # Very intuitive indeed if(not blocking): print(".") # Delay... time.sleep(1) # Read next code s = pylirc.nextcode(1) # Loop as long as there are more on the queue # (dont want to wait a second if the user pressed many buttons...) while(s): # Print all the configs... for (code) in s: cmd = '' print("Command: %s, Repeat: %d" % (code["config"], code["repeat"])) if(code["config"] == "1"): cmd = url_json + str(lampe_biblio) elif(code["config"] == "2"): cmd = url_json + str(lampe_sofa) if cmd != '': cmd = cmd + toggle_json hf = urllib.urlopen(cmd) print('URL JSON pour Domoticz: ' + cmd) print('Réponse: ' + hf.read()) hf.close # Read next code? if(not blocking): s = pylirc.nextcode(1) else: s = [] # Clean up lirc pylirc.exit()

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 toc

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.

zero@opi:~$ cp pylirc.conf .config/lircrc zero@opi:~$ nano .config/lircrc
... begin button = KEY_1 prog = irexec config = echo -n "Lampes TV " && curl "http://192.168.1.22:8080/json.htm?type=command&param=switchlight&idx=52&switchcmd=Toggle" end begin button = KEY_2 prog = pylirc config = echo -n "Lampe sofa " && curl "http://192.168.1.22:8080/json.htm?type=command&param=switchlight&idx=72&switchcmd=Toggle" end begin button = KEY_3 prog = irexec config = curl -s "http://192.168.1.22:8080/json.htm?type=command&param=switchlight&idx=52&switchcmd=Toggle" > /dev/null end begin button = KEY_4 prog = pylirc config = curl -s "http://192.168.1.22:8080/json.htm?type=command&param=switchlight&idx=72&switchcmd=Toggle" > /dev/null end begin button = KEY_5 prog = irexec config = echo 1 | sudo tee /sys/class/leds/orangepi:red:status/brightness > /dev/null && curl -s "http://192.168.1.22:8080/json.htm?type=command&param=switchlight&idx=52&switchcmd=Toggle" > /dev/null && echo 0 | sudo tee /sys/class/leds/orangepi:red:status/brightness > /dev/null end begin button = KEY_6 prog = irexec config = echo 1 | sudo tee /sys/class/leds/orangepi:red:status/brightness > /dev/null && curl -s "http://192.168.1.22:8080/json.htm?type=command&param=switchlight&idx=72&switchcmd=Toggle" > /dev/null && echo 0 | sudo tee /sys/class/leds/orangepi:red:status/brightness > /dev/null end ....

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.

zero@opi:~$ irexec Lampes TV { "status" : "OK", "title" : "SwitchLight" } Lampes sofa { "status" : "OK", "title" : "SwitchLight" }

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 toc

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.

<-Using Bare Metal IR on the Orange Pi Zero ir-keytable on the Orange Pi Zero->