Iāve spent the whole day understanding Thinger. I had never been in touch with such IoT, Iām just hobbist. Neither I had cross-compiled anything. By other hand, Iām very used to Openwrt and C programming, PICs and Arduino. So it was just matter of time.
After fighting for a while, researching and trying, I sucessfully crosscompiled Thinger into my Openwrt router!
Itās very easy once you know what to do. Thinger uses cmake, we can tell cmake what compiler to use.
I used Ubuntu 18.10 with no problems.
Install basic dependencies:
sudo apt-get update
sudo apt-get -y install dkms build-essential git-core libssl-dev libncurses-dev unzip gawk zlib1g-dev subversion mercurial cmake
Download Openwrt source.
(Current Openwrt Stable version: 18.06.02)
git clone https://github.com/openwrt/openwrt.git
cd openwrt
git checkout v18.06.2
./scripts/feeds update -a
./scripts/feeds install -a
Configure Openwrt
make menuconfig
Now select your Target System and Target profile, and exit saving changes.
Build
make
You can speed it up by using multicore processing
make -j5 (Your CPU cores+1)
Depending on your system, it will take a while.
It took 20 minutes on mine (i7-3770K running at 4.4GHz, 16GB RAM, running on SSD), however, my old Athlon X2 6400 would take 2 hours!
I donāt remember having any errors, I used a fresh Ubuntu system and installed only those dependencies I said.
Download Thinger source:
git clone https://github.com/thinger-io/Linux-Client.git
cd Linux-Client
Edit
Now edit the CMakeLists:
gedit CMakeLists.txt
I deleted all the stuff related with arduino, openssl, etcā¦ as SSL libraries use a lot of space that small routers donāt have!
#---------------------------------------------------------------------------------------------------------------------------
#Change this lines for your Openwrt router. Mine is a WDR4900 with PowerPC processor
#Typical Atheros router will have Mips architecture
#Check the stanging_dir in your openwrt directory and correct these lines.
#---------------------------------------------------------------------------------------------------------------------------
>
set(tools /home/user/openwrt/staging_dir/toolchain-powerpc_8540_gcc-7.3.0_musl)
set(CMAKE_C_COMPILER ${tools}/bin/powerpc-openwrt-linux-musl-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/powerpc-openwrt-linux-musl-g++)
# #Don't edit past this !
cmake_minimum_required(VERSION 2.8.9)
project(thinger)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
#check c++11 support
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
SET(OPEN_SSL 0)
set(SOURCE_FILES src/main.cpp)
add_executable(thinger ${SOURCE_FILES})
target_link_libraries(thinger ${ADDITIONAL_LIBS})
set_target_properties(thinger PROPERTIES COMPILE_DEFINITIONS "DAEMON=0")
Save, and youāre ready!
Edit your src/main.cpp file for your needs.
This was my first test. Yes, itās ugly as hell, but it works!
I did a simple program that reads the first line of the file /tmp/readings.txt, converts the read string into int and sends the result to Thinger.
I have another script running on Openwrt that read the serial port and updates that file.
As the file is located in /tmp, itās stored in the ram, so no stress is done to the flash.
#include "thinger/thinger.h"
#include <stdlib.h>
#include <stdio.h>
#define USER_ID "MyUserID"
#define DEVICE_ID "MyDeviceID"
#define DEVICE_CREDENTIAL "MyDeviceCredential"
int watts;
int GetWatts(void){
FILE *fp;
char str[16];
/* opening file for reading */
fp = fopen("/tmp/readings.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
};
fgets(str, 10, fp); // Read the first line from the file */
str[strlen(str)] = '\0'; // Attach a null character to the end of the string
fclose(fp); // Close file
int w = atoi(str); // Convert the string into integer
return w;
};
int main(int argc, char *argv[])
{
thinger_device thing(USER_ID, DEVICE_ID, DEVICE_CREDENTIAL);
thing["Contador"] >[](pson& out){
out["Watts"] = watts;
};
while(1){
thing.handle();
watts=GetWatts();
thing.stream(thing["Contador"]);
sleep(5);
};
return 0;
};
Now it should compile flawlessly:
sudo chmod +x ./run.sh
./run.sh
However, as the run.sh script runs the executable after compiling, it will drop and error, absolutely normal, because the file is made for our routerās architecture, not our computerās.
As long as you see this at the end, itās OK
[100%] Built target thinger
Transfer the file to openwrt
The easiest way is by scp, as it comes installed in ubuntu by default:
(Assuming we still are inside the Linux-Client folder)
cd build
scp thinger root@192.168.1.1:/usr/bin
Will ask for the password, and done. Of course, you should have set a password in openwrt or the SSH wonāt work.
Now enter the openwrt shell by ssh or telnet:
Important
Thinger needs the libstdc library to work:
opkg update
opkg install libstdcpp
Make thinger executable
chmod +x /usr/bin/thinger
Now it should work!
root@OpenWrt:/# thinger
Error opening file: No such file or directory
[830216.665000]: Not connected!
[830216.666000]: Connecting to iot. thinger. io:25200 ...
[830216.767000]: Connected!
[830216.767000]: Authenticating...
[830216.827000]: Authenticated!
Error opening file: No such file or directory
Of course, that error is because I didnāt create the /tmp/reading.txt file! But the client is working
Letās try something quick:
root@OpenWrt:/# echo "1234">/tmp/readings.txt
root@OpenWrt:/# thinger
[830337.401000]: Not connected!
[830337.402000]: Connecting to iot. thinger. io:25200 ...
[830337.457000]: Connected!
[830337.457000]: Authenticating...
[830337.518000]: Authenticated!
Now my Thinger bucket was receiving data! of course just ""1234.
Good luck everyone!