• 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
#1
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:

Code:
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

Code:
dmesg

you should see something like this:

Code:
[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:

Code:
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:

Code:
lsmod
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:

Code:
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

Code:
# ls -al /lib/libc.so.0
lrwxrwxrwx    1 root     root            21 Sep 11  2015 /lib/libc.so.0 -> libuClibc-0.9.33.2.so
#
write down the version of libc (in our case libuClibc-0.9.33.2) - 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)

Code:
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.

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

Code:
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:

Code:
make

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:

Code:
:~# 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-0.9.33.2
drwxr-xr-x 11 root root 4096 Dec  4 13:57 toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2
:/usr/src/openwrt#


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:

Code:
toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2
libuClibc-0.9.33.2.so
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:

Code:
user@myrouter:~# /tmp/pilight-daemon.bin
-ash: /tmp/pilight-daemon.bin: not found
user@myrouter:~#
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:

Code:
u@x:~# cd /usr/src/openwrt/staging_dir
u@x:/usr/src/openwrt/staging_dir# cd toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/
u@x:/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2# 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-0.9.33.2# 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-0.9.33.2# 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-0.9.33.2# rm -rf usr
u@x:/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2# ln -s ../target-mips_34kc_uClibc-0.9.33.2/usr usr
u@x:/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2# 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):

Code:
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):

Code:
# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
# this one not so much
SET(CMAKE_SYSTEM_VERSION 1)

# 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-0.9.33.2)
SET(CROSS_COMPILE_LIBS /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/lib, /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/usr/lib)
include_directories(SYSTEM /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/include, /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/usr/include)

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
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

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.


Code:
PATH=$PATH:/usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin
export PATH
STAGING_DIR=/usr/src/openwrt/staging_dir
export STAGING_DIR
/usr/src/pilight.openwrtdev# cmake -DCMAKE_TOOLCHAIN_FILE=toolchain-openwrt.cmake
the output you get should look like this:

Code:
-- 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-0.9.33.2/bin/mips-openwrt-linux-gcc
-- Check for working C compiler: /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc -- 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-0.9.33.2/bin/mips-openwrt-linux-g++
-- Check for working CXX compiler: /usr/src/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++ -- 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-0.9.33.2/usr/lib/libpcap.so)
-- 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  

-- WARNING --
Manually compiling and installing pilight will also clear all module folders:
/usr/local/lib/pilight/protocols/
/usr/local/lib/pilight/hardware/
/usr/local/lib/pilight/actions/
/usr/local/lib/pilight/operators/
-- WARNING --

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

Code:
make
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 :

Code:
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>
#else
-       #include <execinfo.h>
+//     #include <execinfo.h>
        #define UNW_LOCAL_ONLY
        #ifndef __mips__
                #include <libunwind.h>

for openwrt trunk :

Code:
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) {
    FD_ZERO(&readset);
    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>
#else
-    #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;
#else
-    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;
#endif
    timeradd(&tNow, &tLong, &tEnd);

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

@@ -110,7 +110,7 @@ void delayMicroseconds(unsigned int howLong) {
#ifdef _WIN32
        sleeper.tv_sec = wSecs;
#else
-        sleeper.tv_sec = (__time_t)wSecs;    
+        sleeper.tv_sec = (time_t)wSecs;    
#endif
        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:

Code:
libpthread
librt
libpcap

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

Code:
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.
 
Reply
#2
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
 
Reply
#3
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.
 
Reply
#4
The latest LibreOffice works great Smile
 
Reply
#5
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:
Code:
#!/bin/sh /etc/rc.common
# Copyright (C) 2008-2014 OpenWrt.org

START=99
STOP=99

USE_PROCD=1
#PROG=/bin/pilight-daemon
PROG=/usr/bin/pilight-watchdog
NAME=pilight

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 127.0.0.1
    procd_open_instance
    procd_set_param command "$PROG"
    procd_close_instance
}

stop_service () {
    killall pilight-daemon
        procd_open_instance            
        procd_set_param command "pilight-daemon"
        procd_close_instance
        kill -9 `pidof pilight-daemon`
        sleep 1            
    #ping -c 2 127.0.0.1
        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

Code:
#!/bin/sh

NUMRETRIES=3
DELAYRETRIES=10
DELAYSLEEP=10
NUMTRIED=0

echo start0

#/usr/bin/pilight-daemon &

#sleep $DELAYRETRIES

echo start1

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


Possibly Related Threads...
Thread Author Replies Views Last Post
  rpi3 Buster Compile Error Nikau 9 1,349 03-26-2020, 08:47 AM
Last Post: tvdgeer
  pilight bugs Ascenion 1 283 03-23-2020, 06:29 PM
Last Post: curlymo
  [Solved] pilight service crashing on first webserver access after reboot VrahoK 20 2,288 12-21-2019, 09:46 AM
Last Post: curlymo
  pilight-control modify values coolinx 16 1,986 11-13-2019, 08:02 PM
Last Post: curlymo
  Bug: double free or corruption in pilight-send blackzombie 12 1,632 10-07-2019, 08:15 PM
Last Post: blackzombie
  [Fixed] High CPU usage when pilight usb nano disconnects DieterK 1 617 08-13-2019, 05:43 PM
Last Post: curlymo
  pilight Nano USB interface curlymo 228 125,433 07-10-2019, 06:14 PM
Last Post: curlymo
  problems compiling pilight on Odroid C2 WitchDoctor 101 20,025 03-14-2019, 09:01 PM
Last Post: curlymo
  pilight 8 what chages for custom protocols? polo 11 4,729 02-15-2019, 06:22 PM
Last Post: polo
  v8.1.3 compile error without https fourty2 3 1,007 11-21-2018, 08:02 PM
Last Post: fourty2

Forum Jump:


Browsing: 1 Guest(s)