Click here to Skip to main content
13,595,908 members
Click here to Skip to main content
Add your own
alternative version


8 bookmarked
Posted 22 Jan 2018
Licenced CPOL

IoT Starter Raspberry Pi Lirc

, 15 Feb 2018
Rate this:
Please Sign up or sign in to vote.
IoT.Starter.Pi.Thing powered by Linux Infrared Remote Control


This series, started by IoT.Starter.Pi.Core, introduced in the second part of the IoT.Starter.Pi.Thing, designed as a starter kit for IoT initiatives using Raspberry Pi with Linux.

Based on facts below:

  • We'd be able to extract most from RPI if we better explore the brilliant developments from Linux we already have.
  • Most home automation initiatives should handle legacy infrared (IR) controlled gadgets we have at home, including sound, image, air, heater, etc.
  • There are several RGB leds, led stripes and other low cost IR controlled lighting devices available today. Integrating low cost IR RGB led to the IoT initiatives is a good opportunity to be explored.
  • Linux Lirc is a mature and wide project. There is a big remote database containing config files for remote controls with more than 2,500 devices and counting.
  • IoT.Starter.Pi.Thing can benefit from Lirc installed at RPI, we just need to link them.

The specification for current mission is to provide infrared (IR) output capability to IoT.Starter.Pi.Thing projects. Home gadgets following the lead of universal remote controls has been a desired dream for home automation initiatives of all times.

LIRC: Linux Infrared Remote Control for Raspberry Pi

The Linux Infrared Remote Control for Raspberry Pi is derived from the original Lirc serial driver by Aron Szabo. A further development by Bengt Martensson improved the Lirc driver. The good news, for you installing Lirc for the first time, is that Raspberry Pi / Raspbian Stretch comes with Lircd (version 0.9.4c here), improved to make your life better. Files required in the previous version are not used anymore: /etc/modules and /etc/lirc/hardware.conf

Lirc install

In order to update and upgrade Raspbian and install Lirc at RPI, run the command:

apt-get update \
  && apt-get upgrade -y \
  && apt-get install -y lirc \
  && rm -rf /var/lib/apt/lists/*


The Lirc version 0.9.4c is configured ONLY by file /boot/config.txt.

Add to /boot/config.txt:

# Uncomment this to enable the lirc-rpi module

Change Default Driver

Edit file /etc/lirc/lirc_options.conf and change:

driver  = devinput
device  = auto

driver  = default
device  = /dev/lirc0

Reboot and Check

Please check more details about Lirc installation at RPI Setup instructions available in the project repo. Following is a quick check to evaluate Lirc installation.

lircd status

/etc/init.d/lircd status
[ ok ] lircd is running.


lsmod | grep lirc
lirc_rpi                9032  0
lirc_dev               10583  1 lirc_rpi
rc_core                24377  1 lirc_dev


mode2 --driver default --list-devices

Checking Available Remotes and their Respective IR Codes

pi@lumi:~ $ irsend list "" ""

pi@lumi:~ $ irsend list LED_24_KEY ""

0000000000000001 BRIGHT_DOWN
0000000000000002 BRIGHT_UP
0000000000000003 OFF
0000000000000004 ON
0000000000000005 RED
0000000000000006 GREEN
0000000000000007 BLUE
0000000000000008 WHITE
0000000000000009 ORANGE
000000000000000a PEA_GREEN
000000000000000b DARK_BLUE
000000000000000c 7_JUMP
000000000000000d DARK_YELLOW
000000000000000e CYAN
000000000000000f BROWN
0000000000000010 ALL_FADE
0000000000000011 YELLOW
0000000000000012 LIGHT_BLUE
0000000000000013 PINK
0000000000000014 7_FADE
0000000000000015 STRAW_YELLOW
0000000000000016 SKY_BLUE
0000000000000017 PURPLE
0000000000000018 3_JUMP

Blasting IR Commands to RGB Lights

# turn on
pi@lumi:~ $ irsend SEND_ONCE LED_44_KEY POWER
#change color
pi@lumi:~ $ irsend SEND_ONCE LED_44_KEY WHITE
pi@lumi:~ $ irsend SEND_ONCE LED_44_KEY CYAN
pi@lumi:~ $ irsend SEND_ONCE LED_44_KEY WHITE
# lights up and down
pi@lumi:~ $ irsend --count=10 SEND_ONCE LED_44_KEY BRIGHT_UP
pi@lumi:~ $ irsend --count=10 SEND_ONCE LED_44_KEY BRIGHT_UP
pi@lumi:~ $ irsend --count=20 SEND_ONCE LED_44_KEY BRIGHT_DOWN
pi@lumi:~ $ irsend --count=10 SEND_ONCE LED_44_KEY BRIGHT_UP
# turn off
pi@lumi:~ $ irsend SEND_ONCE LED_44_KEY POWER


Lirc-Console extends IoT.Starter.Pi.Thing projects to use Linux Infrared Remote Control.

Please note that, until now, home-ui and home-web projects were built with no knowledge about Lirc. The lirconsoleobjective is to start Lirc commands from a docker container, and communicate with Lirc installed at RPI host. As we will see, the irsend command will play an important role here, identifying remotes, their corresponding codes, and blasting IR led streams to control home equipment.

Console program is a simple loop, as shown below, that echoes commands.

class Program
    static void Main(string[] args)
        Console.WriteLine("Hello World!");

        string example = "";

        while (!example.ToLower().Equals("x"))
            example = Console.ReadLine();


The ShellHelper class suggested by does the dirty job, starting a bash process, capturing the answer, and returning the string result.

public static class ShellHelper
    public static string Bash(this string cmd)
        var escapedArgs = cmd.Replace("\"", "\\\"");

        var process = new Process()
            StartInfo = new ProcessStartInfo
                FileName = "/bin/bash",
                Arguments = $"-c \"{escapedArgs}\"",
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true,
        string result = process.StandardOutput.ReadToEnd();
        return result;

Well done. Actually, we have now reached the real job at this mission.

Lirc on docker Container

Based on the original Lirc basic setup flow, the edited diagram below shows Lirc installed at RPI host. It includes all low level devices, drivers, lircd socket and lircd.conf configuration files, they are all installed at RPI host, near hardware level.

      |  remote  |

        (air gap)

      ! capture  !
      ! device   !
      ! kernel   !                   Sometimes needs
      ! driver   !                   modprobe(1) configuration.
           v  IR pulse data          Device like /dev/lirc0, /dev/ttyACM0.
           |                         or /dev/ttyS0.
      |  lirc    |                   Configure lirc_options.conf
      |  driver  |                   with driver and usually also device.
           v  IR pulse data          Use mode2(1) to debug
   |  lirc pass 1 |                  lircd.conf config file.
           v  Key symbols            Output socket e. g.,
           |                         /var/run/lirc/lircd. Use irw(1) to debug.
   |  lirconsole  |                  lirconsole app.

At the bottom, the lirconsole program is running inside the docker container. Communicating through the lircd socket, a docker volume enables data sharing between host and container. Following are the Lirc-compose.yml and Lirc.dockerfile that do the entire job.


The volume is created exactly at socket area: /var/run/lirc. This ensures proper communication between containers running irsend commands and Lirc output socket installed at RPI host.

version: '3'

    container_name: lirconsole
    image: josemottalopes/lirconsole
      context: .
      dockerfile: Lirc/lirc.Dockerfile
    network_mode: bridge
    privileged: true
    - /var/run/lirc:/var/run/lirc


As usual, the dotnet:2.0.0-runtime-stretch-arm32v7 image is used as base and the OS is updated and upgraded before installing Lirc. After Lirc package installation, the RPI configuration is copied to Lirc inside container. This assures that remotes that are installed at RPI host be seen by docker container software. The /boot/config.txt is updated and remote config files are moved to /etc/lirc/lircd.conf.d, in order to keep the same setup installed at RPI host.

FROM microsoft/dotnet:2.0.0-runtime-stretch-arm32v7 AS base

  apt-get update \
  && apt-get upgrade -y \
  && apt-get install -y \
       lirc \
  --no-install-recommends && \
  rm -rf /var/lib/apt/lists/*

  mkdir -p /var/run/lirc \
  && rm -f /etc/lirc/lircd.conf.d/devinput.*

COPY Lirc/setup/config.txt /boot/config.txt
COPY Lirc/setup/lirc_options.conf /etc/lirc/lirc_options.conf 
COPY Lirc/setup/ir-remote.conf /etc/modprobe.d/ir-remote.conf
COPY Lirc/remotes /etc/lirc/lircd.conf.d

FROM microsoft/dotnet:2.0-sdk AS build
COPY *.sln .
COPY Contest/Contest.csproj Contest/
RUN dotnet restore
COPY . .
WORKDIR /src/Contest
RUN dotnet build -c Release -r linux-arm -o /app

FROM build AS publish
RUN dotnet publish -c Release -r linux-arm -o /app

FROM base AS final
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Contest.dll"]

Finally, the Contest console program is built and copied to the base image. The entry point is set exactly at the console program. It is now time to build and push the image to DockerHub.

Building and Pushing to Dockerhub

You can notice that several dockerfile and docker-compose files were kept in the solution. To build the lirconsole properly, the lirc-compose.yml and lirc.Dockerfile files should be used, as shown in the session below:

$ docker-compose -f lirc-compose.yml build
Building lirc
Step 1/24 : FROM microsoft/dotnet:2.0.0-runtime-stretch-arm32v7 AS base
 ---> 6354e860c381
Step 2/24 : WORKDIR /app
 ---> Using cache
 ---> 05412cd53d5a
 ---> Using cache
 ---> 12cf4637e50e
Step 4/24 : RUN apt-get update   && apt-get upgrade -y   
&& apt-get install -y --no-install-recommends        lirc   && rm -rf /var/lib/apt/lists/*
 ---> Using cache
 ---> 0b28f4942ec9
Step 5/24 : RUN mkdir -p /var/run/lirc   && rm -f /etc/lirc/lircd.conf.d/devinput.*
 ---> Using cache
 ---> 8599c290104e
Step 6/24 : COPY Lirc/setup/config.txt /boot/config.txt
 ---> Using cache
 ---> 1b90462496c0
Step 7/24 : COPY Lirc/setup/lirc_options.conf /etc/lirc/lirc_options.conf
 ---> Using cache
 ---> 4270b263f046
Step 8/24 : COPY Lirc/setup/ir-remote.conf /etc/modprobe.d/ir-remote.conf
 ---> Using cache
 ---> 19ac2e2872ff
Step 9/24 : COPY Lirc/remotes /etc/lirc/lircd.conf.d
 ---> Using cache
 ---> 4a710c8d0f7d
Step 10/24 : FROM microsoft/dotnet:2.0-sdk AS build
 ---> 730e3899d926
Step 11/24 : WORKDIR /src
 ---> e8abbbf5f6e9
Removing intermediate container 8a58bc431b60
 ---> Running in 6def39dc1fa7
 ---> 9aebdfd73284
Removing intermediate container 6def39dc1fa7
Step 13/24 : COPY *.sln .
 ---> 5e860a31d313
Step 14/24 : COPY Contest/Contest.csproj Contest/
 ---> 8a3caeb83910
Step 15/24 : RUN dotnet restore
 ---> Running in d0f9d060571c
/usr/share/dotnet/sdk/2.1.4/NuGet.targets(227,5): warning MSB3202: 
The project file "/src/docker-compose.dcproj" was not found. [/src/Console.sln]
/src/docker-compose.dcproj : warning NU1503: Skipping restore for project 
'/src/docker-compose.dcproj'. The project file may be invalid or 
missing targets required for restore. [/src/Console.sln]
  Restoring packages for /src/Contest/Contest.csproj...
  Generating MSBuild file /src/Contest/obj/Contest.csproj.nuget.g.props.
  Generating MSBuild file /src/Contest/obj/Contest.csproj.nuget.g.targets.
  Restore completed in 198.79 ms for /src/Contest/Contest.csproj.
 ---> 209d1043c558
Removing intermediate container d0f9d060571c
Step 16/24 : COPY . .
 ---> 192e92eeb6c8
Step 17/24 : WORKDIR /src/Contest
 ---> 519396d48efb
Removing intermediate container 331d28acecc3
Step 18/24 : RUN dotnet build -c Release -r linux-arm -o /app
 ---> Running in f5f581f9dda0
Microsoft (R) Build Engine version for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restoring packages for /src/Contest/Contest.csproj...
  Installing runtime.linux-arm.Microsoft.NETCore.DotNetAppHost 2.0.0.
  Installing runtime.linux-arm.Microsoft.NETCore.DotNetHostResolver 2.0.0.
  Installing runtime.linux-arm.Microsoft.NETCore.DotNetHostPolicy 2.0.0.
  Installing runtime.linux-arm.Microsoft.NETCore.App 2.0.0.
  Restore completed in 6.63 sec for /src/Contest/Contest.csproj.
  Contest -> /app/Contest.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:09.49
 ---> 5118d530dace
Removing intermediate container f5f581f9dda0
Step 19/24 : FROM build AS publish
 ---> 5118d530dace
Step 20/24 : RUN dotnet publish -c Release -r linux-arm -o /app
 ---> Running in 6d95b1cdfa40
Microsoft (R) Build Engine version for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 24.35 ms for /src/Contest/Contest.csproj.
  Contest -> /src/Contest/bin/Release/netcoreapp2.0/linux-arm/Contest.dll
  Contest -> /app/
 ---> 55409c2731a0
Removing intermediate container 6d95b1cdfa40
Step 21/24 : FROM base AS final
 ---> 4a710c8d0f7d
Step 22/24 : WORKDIR /app
 ---> Using cache
 ---> a2ea12d478d4
Step 23/24 : COPY --from=publish /app .
 ---> Using cache
 ---> 45d03827ff17
Step 24/24 : ENTRYPOINT dotnet Contest.dll
 ---> Using cache
 ---> 4b8ec200357a
Successfully built 4b8ec200357a
Successfully tagged josemottalopes/lirconsole:latest

jo@CANOAS24 MINGW64 /c/_git/Lirc-Console/Console (master)
$ docker push josemottalopes/lirconsole
The push refers to a repository []
bdfbceb06300: Mounted from josemottalopes/home-lirc
a5263a5a63ea: Mounted from josemottalopes/home-lirc
0308d77027ae: Mounted from josemottalopes/home-lirc
736189974ffd: Mounted from josemottalopes/home-lirc
6c15a4e79b6c: Mounted from josemottalopes/home-lirc
38cd25f9bbe4: Mounted from josemottalopes/home-lirc
f4dd319f6d5c: Mounted from josemottalopes/home-lirc
aa89badf53d9: Mounted from josemottalopes/conlirc
202255094ceb: Mounted from josemottalopes/conlirc
649673d2d837: Mounted from josemottalopes/conlirc
643a426f2599: Mounted from josemottalopes/conlirc
ccd48fa5ba35: Mounted from josemottalopes/conlirc
latest: digest: sha256:45413fab32528e3649035fb2e1af90c0f8e80272d7b93ae00f8949cff141b454 size: 2829

Finally, the image josemottalopes/lirconsole is pushed to the Dockerhub.

Pulling and Running at RPI

Below the docker command to load and run lirconsole at RPI. Please note that Lirc should be properly installed and configured according to RPI Setup instructions.

docker run -it --name home-lirc --privileged 
-v /var/run/lirc:/var/run/lirc josemottalopes/lirconsole:latest

The test session below starts with Hello World! message. Then, the available remotes are listed by irsend list "" "". You can check that there is a Samsung IR remote control in the list. Last, the irsend command is used again, commanding the "volume down" key of Samsung monitor.

root@lumi:~# docker run -it --privileged --name lirconsole 
-v /var/run/lirc:/var/run/lirc josemottalopes/lirconsole:latest
Unable to find image 'josemottalopes/lirconsole:latest' locally
latest: Pulling from josemottalopes/lirconsole
Digest: sha256:45413fab32528e3649035fb2e1af90c0f8e80272d7b93ae00f8949cff141b454
Status: Downloaded newer image for josemottalopes/lirconsole:latest
Hello World!
irsend list "" ""
irsend list "" ""

irsend send_once Samsung_BN59-00678A KEY_VOLUMEDOWN
irsend send_once Samsung_BN59-00678A KEY_VOLUMEDOWN

irsend send_once Samsung_BN59-00678A KEY_VOLUMEDOWN
irsend send_once Samsung_BN59-00678A KEY_VOLUMEDOWN

/bin/bash: x: command not found


Mission Accomplished

As shown in the photo below, the monitor acknowledged and accepted the IR output command to decrease the volume.

Have fun!



This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Jose Motta
Systems Engineer
Brazil Brazil
Electronic Engineer UFRJ 1977, M.Sc. Computer Systems COPPE 1982, CEPEL Researcher until 1985, Mira Informatica CEO until 1995, TRENDnet Brazil CEO until 2015, IoT Systems & Architecture.

You may also be interested in...

Comments and Discussions

QuestionThank you for the article Pin
Phebous25-Feb-18 19:31
memberPhebous25-Feb-18 19:31 
QuestionMessage Closed Pin
23-Jan-18 0:26
memberMasood raza23-Jan-18 0:26 
QuestionMessage Closed Pin
22-Jan-18 19:43
memberIPL Update22-Jan-18 19:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02 | 2.8.180621.3 | Last Updated 15 Feb 2018
Article Copyright 2018 by Jose Motta
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid