• 10 dec 2017: forum version update. In case of issues use this topic.
  • 30 nov 2017: pilight moved servers. In case of issues use this topic.
Hello There, Guest! Login Register

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to compile pilight for your OpenWRT Router
How to compile pilight for your openwrt router

Hi everybody,

after having tried (and failed) a couple of times to build my own pilight for my very own openwrt router, I thought I'd write a little howto based on the information I found in this board and elsewhere on the net.

What you need:

1. The openwrt SDK from git.openwrt.org
2. The pilight sources from github
3. a supported router with openwrt and a usb port
4. a pilight nano usb
5. a Unix machine which we use as the building machine

I assume that you are running chaos calmer (15.05), but adapting to other releases should be possible.

First of all you need to prepare your router and see if it recognizes the nano usb.
Arduinos (nano) and clones come with many different UART chips (i.e. USB to serial bridges), such as FTDI, CH340 etc.
To identify the chip you may either do trial-error with the following kernel modules or alternatively take a magnifying glass and look at the chip on the bottom of the arduino nano. Most cheap version come with CH340, others come with FTDI or Silicon Labs CP210x

In order to be able to talk to the UART, your router must have the corresponding driver. Luckily, there are many software packages available. If you are using Luci (i.e. the Web Frontend for OpenWRT) you can log into your router using LuCi, go to System-Software, then select "available packages" and the letter "k", then scroll down to the kmod-usb-serial modules. Install the one that corresponds to your chip:

kmod-usb-serial-ch341    3.18.20-1    Kernel support for Winchiphead CH341 USB-to-Serial converters
kmod-usb-serial-cp210x    3.18.20-1    Kernel support for Silicon Labs cp210x USB-to-Serial converters
kmod-usb-serial-ftdi    3.18.20-1    Kernel support for FTDI USB-to-Serial converters
(in my case kmod-usb-serial-ftdi)

Once the package has been installed, you can check if openwrt recognizes it - ssh or telnet to the router, hook the nano usb up to the usb port on your router and type


you should see something like this:

[10561039.350000] usbcore: registered new interface driver usbserial
[10561039.360000] usbcore: registered new interface driver usbserial_generic
[10561039.360000] usbserial: USB Serial support registered for generic
[10561039.430000] usbcore: registered new interface driver ftdi_sio
[10561039.430000] usbserial: USB Serial support registered for FTDI USB Serial Device
[10561159.070000] usb 2-1: new full-speed USB device number 2 using ehci-platform
[10561159.230000] ftdi_sio 2-1:1.0: FTDI USB Serial Device converter detected
[10561159.240000] usb 2-1: Detected FT232RL
[10561159.250000] usb 2-1: FTDI USB Serial Device converter now attached to ttyUSB0
If you have a look at the /dev directory you can also see the newly created usb serial device:

ls -al /dev
crw-r--r--    1 root     root      188,   0 Dec  3 17:32 ttyUSB0
checking the modules should show that usbserial is loaded and used by the UART:

usb_common              1008  1 usbcore
usbcore               111392  5 ftdi_sio
usbserial              16720  1 ftdi_sio
If you can't see the devices and/or modules then either you have selected the wrong UART or your nano is defective.

Before you start downloading and compiling you should double check that the version of the SDK matches exactly the version of openwrt you are running on the router.
To do this, do the following:

1. SSH to your router. You should see a welcome message like this:

BusyBox v1.23.2 (2015-07-25 15:09:46 CEST) built-in shell (ash)

  _______                     ________        __
|       |.-----.-----.-----.|  |  |  |.----.|  |_
|   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
|_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
CHAOS CALMER (15.05, r46767)
  * 1 1/2 oz Gin            Shake with a glassful
  * 1/4 oz Triple Sec       of broken ice and pour
  * 3/4 oz Lime Juice       unstrained into a goblet.
  * 1 1/2 oz Orange Juice
  * 1 tsp. Grenadine Syrup
In our case the version of openwrt is 15.05 and the build number is r46767. Write this down.

2. Double check the version of libc. Issue a simple

# ls -al /lib/libc.so.0
lrwxrwxrwx    1 root     root            21 Sep 11  2015 /lib/libc.so.0 -> libuClibc-
write down the version of libc (in our case libuClibc- - why? If you accidentally use the wrong version, after building your binary and trying to run it on your router, you will get a "file not found" error.

Checking the openwrt Wiki https://wiki.openwrt.org/about/history , our release is the september 2015 release of chaos calmer (the build number has to match).
Back to our building machine.
Now we can download the SDK (to distinguish the sub directory from other releases I called it /usr/src/openwrt.r46767)

git clone https://git.openwrt.org/15.05/openwrt.git /usr/src/openwrt.r46767
In order to make things a bit easier I create a symbolic link to the version I am working with.

cd /usr/src
ln -s openwrt.r46767 openwrt
we can now cd into that directory and build the SDK

cd openwrt
make menuconfig
Select the following options:

Under Target System select your architecture
Alternatively under Target Profile select your router as you probably don't need the bootfile images for all the others
Under libraries select libpcap and possibly libunwind (if it is there)

Save the config by selecting Exit and answer yes, save. Your config is now stored in .config. Now start the build:


It is now time to go to the gym, for a long walk with your dog or work in the garden. This takes a while. (on my i5 it took roughly 2 hours)

(to be continued)

Once the build is finished, it will use several GBs of storage on your harddrive. In the openwrt/staging_dir you should have three subdirectories:

:~# cd /usr/src/openwrt
:/usr/src/openwrt# ls -al staging_dir
total 20
drwxr-xr-x  5 root root 4096 Dec  4 12:48 .
drwxr-xr-x 15 root root 4096 Dec  4 12:48 ..
drwxr-xr-x 12 root root 4096 Dec  4 13:12 host
drwxr-xr-x  6 root root 4096 Dec  4 12:48 target-mips_34kc_uClibc-
drwxr-xr-x 11 root root 4096 Dec  4 13:57 toolchain-mips_34kc_gcc-4.8-linaro_uClibc-

These names are quite long and include the processor architecture and the gcc version it has beeen built with as well as the libc version which we have written down in the beginning.

Double check that the versions are matching:

They do match in our case so we can safely continue.

If they do not match, you have downloaded the wrong SDK and you have to fix this before you continue. If you don't, calling the pilight binaries on your router will throw a stupid error such as:

user@myrouter:~# /tmp/pilight-daemon.bin
-ash: /tmp/pilight-daemon.bin: not found
The next step is to simplify things a little bit and also make the libpcap (and possibly libunwind) libraries and header files available to pilight.
Whilst the C libraries are located under the toolchain directory, the above mentioned files are under the target directory.

In order to fix this I have chosen to just link the usr subdirectory of the toolchain (which is empty) to the usr directory of the target:

u@x:~# cd /usr/src/openwrt/staging_dir
u@x:/usr/src/openwrt/staging_dir# cd toolchain-mips_34kc_gcc-4.8-linaro_uClibc-
u@x:/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc- ls -al usr
total 16
drwxr-xr-x  4 root root 4096 Dec  4 12:48 .
drwxr-xr-x 12 root root 4096 Dec  4 14:14 ..
drwxr-xr-x  2 root root 4096 Dec  4 12:48 include
drwxr-xr-x  2 root root 4096 Dec  4 12:48 lib
u@x:/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc- ls -al usr/include/
total 8
drwxr-xr-x 2 root root 4096 Dec  4 12:48 .
drwxr-xr-x 4 root root 4096 Dec  4 12:48 ..
u@x:/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc- ls -al usr/lib    
total 8
drwxr-xr-x 2 root root 4096 Dec  4 12:48 .
drwxr-xr-x 4 root root 4096 Dec  4 12:48 ..
u@x:/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc- rm -rf usr
u@x:/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc- ln -s ../target-mips_34kc_uClibc- usr
u@x:/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc- ls -al usr/lib/libpcap*
-rw-r--r-- 1 root root 257122 Dec  4 14:32 usr/lib/libpcap.a
lrwxrwxrwx 1 root root     14 Dec  4 14:32 usr/lib/libpcap.so -> libpcap.so.1.3
lrwxrwxrwx 1 root root     16 Dec  4 14:32 usr/lib/libpcap.so.1.3 -> libpcap.so.1.3.0
-rw-r--r-- 1 root root 200982 Dec  4 14:32 usr/lib/libpcap.so.1.3.0
(there might be a better solution to this - if anybody knows, please post a comment - for the time being this works fine)

OK, so far for the openwrt environment. Now let's move over to preparing and compiling pilight.
First, start by pulling a clean image from github - chose either development or master as a branch name here (I use development which I clone into a subdirectory named pilight.openwrtdev):

u@x:/usr/src# git clone -b development https://github.com/pilight/pilight pilight.openwrtdev
Cloning into 'pilight.openwrtdev'...
remote: Counting objects: 15580, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 15580 (delta 2), reused 0 (delta 0), pack-reused 15573
Receiving objects: 100% (15580/15580), 11.02 MiB | 5.93 MiB/s, done.
Resolving deltas: 100% (11929/11929), done.
Checking connectivity... done.
u@x:/usr/src# cd pilight.openwrtdev
u@x:/usr/src/pilight.openwrtdev# vi toolchain-openwrt.cmake
put the following text into the toolchain-openwrt.cmake file (based on the work by Forumkel in this post):

# this one is important
# this one not so much

# specify the cross compiler
SET(CMAKE_C_COMPILER   mips-openwrt-linux-gcc)
SET(CMAKE_CXX_COMPILER mips-openwrt-linux-g++)

# where is the target environment
SET(CMAKE_FIND_ROOT_PATH  /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-
SET(CROSS_COMPILE_LIBS /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-, /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-
include_directories(SYSTEM /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-, /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer")

# search for programs in the build host directories
# for libraries and headers in the target directories

Now it is time to see if we can make cmake happy with the file. First we need to tell our shell where to find the compilers etc.

export PATH
/usr/src/pilight.openwrtdev# cmake -DCMAKE_TOOLCHAIN_FILE=toolchain-openwrt.cmake
the output you get should look like this:

-- The C compiler identification is GNU 4.8.3
-- The CXX compiler identification is GNU 4.8.3
-- Check for working C compiler: /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-
-- Check for working C compiler: /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc- -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-
-- Check for working CXX compiler: /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc- -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Looking for libpcap - found (/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-
-- Looking for include file pthread.h
-- Looking for include file pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  

Manually compiling and installing pilight will also clear all module folders:

-- Configuring done
-- Generating done
-- Build files have been written to: /usr/src/pilight.openwrtdev
Now we can start to build by just typing

Compiling might break at various points due to the different scalar types in gc/uclib and/or missing header files. The changes I had to make to the sources are as follow:

for openwrt 15.05 :

u@x:/usr/src/pilight.openwrtdev# git diff
diff --git a/libs/pilight/core/gc.c b/libs/pilight/core/gc.c
index 1a6bfde..326e1e1 100644
--- a/libs/pilight/core/gc.c
+++ b/libs/pilight/core/gc.c
@@ -25,7 +25,7 @@
#ifdef _WIN32
        #include <windows.h>
-       #include <execinfo.h>
+//     #include <execinfo.h>
        #define UNW_LOCAL_ONLY
        #ifndef __mips__
                #include <libunwind.h>

for openwrt trunk :

diff --git a/libs/pilight/core/arp.c b/libs/pilight/core/arp.c
index f0ca84a..5c53708 100644
--- a/libs/pilight/core/arp.c
+++ b/libs/pilight/core/arp.c
@@ -396,8 +396,8 @@ static int recvfrom_wto(long unsigned int tmo, pcap_t *pcap_handle) {
    if(pcap_fd >= 0)
        FD_SET(pcap_fd, &readset);
-        to.tv_sec  = (__time_t)(tmo/(long unsigned int)1000000);
-        to.tv_usec = (__suseconds_t)(tmo - (long unsigned int)((time_t)1000000 * to.tv_sec));
+        to.tv_sec  = (time_t)(tmo/(long unsigned int)1000000);
+        to.tv_usec = (suseconds_t)(tmo - (long unsigned int)((time_t)1000000 * to.tv_sec));
        n = select(pcap_fd+1, &readset, NULL, NULL, &to);
    if(n < 0) {
        logprintf(LOG_ERR, "select");
diff --git a/libs/pilight/core/gc.c b/libs/pilight/core/gc.c
index 1a6bfde..b4fb03b 100644
--- a/libs/pilight/core/gc.c
+++ b/libs/pilight/core/gc.c
@@ -25,7 +25,7 @@
#ifdef _WIN32
    #include <windows.h>
-    #include <execinfo.h>
+    //#include <execinfo.h>
    #define UNW_LOCAL_ONLY
    #ifndef __mips__
        #include <libunwind.h>
diff --git a/libs/pilight/hardware/433gpio.c b/libs/pilight/hardware/433gpio.c
index a448396..317f358 100644
--- a/libs/pilight/hardware/433gpio.c
+++ b/libs/pilight/hardware/433gpio.c
@@ -73,10 +73,10 @@ static int gpio433Send(int *code, int rawlen, int repeats) {
        for(r=0;r<repeats;r++) {
            for(x=0;x<rawlen;x+=2) {
                digitalWrite(gpio_433_out, 1);
-                usleep((__useconds_t)code[x]);
+                usleep((useconds_t)code[x]);
                digitalWrite(gpio_433_out, 0);
                if(x+1 < rawlen) {
-                    usleep((__useconds_t)code[x+1]);
+                    usleep((useconds_t)code[x+1]);
diff --git a/libs/wiringx/wiringX.c b/libs/wiringx/wiringX.c
index f9d3351..db96722 100644
--- a/libs/wiringx/wiringX.c
+++ b/libs/wiringx/wiringX.c
@@ -82,8 +82,8 @@ static void delayMicrosecondsHard(unsigned int howLong) {
    tLong.tv_sec  = howLong / 1000000;
    tLong.tv_usec = howLong % 1000000;
-    tLong.tv_sec  = (__time_t)howLong / 1000000;
-    tLong.tv_usec = (__suseconds_t)howLong % 1000000;
+    tLong.tv_sec  = (time_t)howLong / 1000000;
+    tLong.tv_usec = (suseconds_t)howLong % 1000000;
    timeradd(&tNow, &tLong, &tEnd);

@@ -98,7 +98,7 @@ void delayMicroseconds(unsigned int howLong) {
    long int uSecs = howLong % 1000000;
    unsigned int wSecs = howLong / 1000000;
-    long int uSecs = (__time_t)howLong % 1000000;
+    long int uSecs = (time_t)howLong % 1000000;
    unsigned int wSecs = howLong / 1000000;

@@ -110,7 +110,7 @@ void delayMicroseconds(unsigned int howLong) {
#ifdef _WIN32
        sleeper.tv_sec = wSecs;
-        sleeper.tv_sec = (__time_t)wSecs;    
+        sleeper.tv_sec = (time_t)wSecs;    
        sleeper.tv_nsec = (long)(uSecs * 1000L);
        nanosleep(&sleeper, NULL);

OK, if everything goes well you should now have a binary of your daemon etc.

Before I was able to launch it on my router I had to install the following additional opackages:


I then copied the daemon over to the router using scp:

scp pilight-daemon root@myrouter:/bin
before you can launch it you need of course an etc/pilight/config.json and possibly an etc/init.d/pilight to start the daemon automatically at boot time.
but that's another story.
Nice walkthrough!

If you want to, it would be great if you could add this to the pilight manual's installation instructions (https://manual.pilight.org/en/installation#pf2). The documents are hosted on GitHub, https://github.com/pilight/pilight-manual. Smile
Hi pilino1234, happy to do this. However, it turns out that my OpenOffice Version doesn't seem to support the fodt XML format - I'll have to take a closer look into this, but as we are approaching quarter end it's quite busy on my end. I will give this a try over christmas.
The latest LibreOffice works great Smile
Sorry guys, have been very very busy - but had some time lately to fix a couple of issues.

I have found out that pilight crashes on openwrt after a day or so (not great if you use it for fire alarm...) - rather than fixing the root cause I have built a quick and dirty fix by adding a watchdog. What I have also found out is that if you unplug the pilight nano usb, the pilight daemon goes to 100% cpu and crashes after a couple of seconds.

In order to relaunch it, I have to unload the whole usb stack on the router and reload it. Luckily, usb is compiled in modules, so rmmod/modprobe does the trick.

Here is my /etc/init.d/pilight:
#!/bin/sh /etc/rc.common
# Copyright (C) 2008-2014 OpenWrt.org



start_service () {
    rmmod ftdi_sio
    rmmod ch341
    rmmod usbserial
    rmmod ledtrig_usbdev
    rmmod ehci_platform
    rmmod ehci_hcd
    rmmod usbcore
    rmmod usb_common
    modprobe usb_common
    modprobe usbcore
    modprobe ehci_hcd
    modprobe ehci_platform
    modprobe ledtrig_usbdev
    modprobe usbserial
    modprobe ch341
    modprobe ftdi_sio
    sleep 1
    #ping -c 2
    procd_set_param command "$PROG"

stop_service () {
    killall pilight-daemon
        procd_set_param command "pilight-daemon"
        kill -9 `pidof pilight-daemon`
        sleep 1            
    #ping -c 2
        rmmod ftdi_sio
        rmmod ch341
        rmmod usbserial

stop() {          
        echo stop
    /usr/bin/killall pilight-daemon
        # commands to kill application

and my /usr/bin/pilight-watchdog



echo start0

#/usr/bin/pilight-daemon &


echo start1

while true; do
    echo start2
    while [ ! `pidof pilight-daemon`  ] &&  [ $NUMTRIED -le $NUMRETRIES ]  
        echo pilight not running - respawning
        /usr/bin/pilight-daemon &
        echo "tried $NUMTRIED times"
        sleep $DELAYRETRIES    
    echo ok
    sleep $DELAYSLEEP

Possibly Related Threads...
Thread Author Replies Views Last Post
  pilight start/stop loop Rschnauzer 1 222 10-27-2022, 10:28 PM
Last Post: Rschnauzer
  pilight on raspbian bullseye ChristianK 3 1,545 07-29-2022, 10:18 PM
Last Post: Henkehh
  pilight-raw changes output format from 7 to 8 Rschnauzer 2 1,609 05-04-2022, 01:32 PM
Last Post: youradultworld
Question pilight stopped working sl4m01 5 2,447 09-16-2021, 01:34 PM
Last Post: orlo11
  how to compile pilight with custom protocol code? am i missing something? stanwebber 2 982 07-05-2021, 03:49 AM
Last Post: stanwebber
  Staging does not compile with new backtrace? akloeckner 1 827 05-16-2021, 07:48 AM
Last Post: akloeckner
  hardware info lost after pilight restart Rschnauzer 3 1,227 03-17-2021, 11:44 AM
Last Post: Rschnauzer
Question pilight nightly webgui offline after some hours fleisch 4 1,696 10-26-2020, 05:19 PM
Last Post: fleisch
  rpi3 Buster Compile Error Nikau 9 4,364 03-26-2020, 08:47 AM
Last Post: tvdgeer
  pilight bugs Ascenion 1 1,220 03-23-2020, 06:29 PM
Last Post: curlymo

Forum Jump:

Browsing: 1 Guest(s)