Merge branch 'master' of http://master.iot-yun.club:8088/r/raspberrypi
9 files modified
27 files deleted
44 files added
1 files renamed
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | ARCH=`uname -m` |
| | | |
| | | echo ${ARCH} | grep "arm" > /dev/null |
| | | if [ $? != 0 ] ; then |
| | | echo "+---------------------------------------------------+" |
| | | echo "| ERROR: This folder must compile on RaspberryPi |"; |
| | | echo "+---------------------------------------------------+" |
| | | exit 1; |
| | | fi |
| | | |
| | | |
| | | function do_compile |
| | | { |
| | | for dir in `ls` |
| | | do |
| | | if [ -f $dir/build*.sh ] ; then |
| | | cd $dir |
| | | ./build*.sh |
| | | cd - |
| | | fi |
| | | done |
| | | } |
| | | |
| | | function do_clean |
| | | { |
| | | for dir in `ls` |
| | | do |
| | | if [ -f $dir/build*.sh ] ; then |
| | | rm -rf ${dir}/${dir}* |
| | | fi |
| | | done |
| | | |
| | | rm -rf install |
| | | } |
| | | |
| | | if [[ $# == 1 ]] && [[ $1 == "clean" ]] ; then |
| | | do_clean |
| | | exit; |
| | | fi |
| | | |
| | | do_compile |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | #+-------------------------------------------------------------------------------------------- |
| | | #|Description: This shell script used download and compile cJSON for RaspberryPi |
| | | #| Author: GuoWenxue <guowenxue@gmail.com> |
| | | #| ChangeLog: |
| | | #| 1, Initialize 1.0.0 on 2021.04.12 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | PREFIX_PATH=/usr |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | function check_result() |
| | | { |
| | | if [ $? != 0 ] ; then |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | exit ; |
| | | fi |
| | | } |
| | | |
| | | function compile_cJSON() |
| | | { |
| | | SRC_NAME=cJSON-1.7.15 |
| | | PACK_SUFIX=tar.gz |
| | | IMG_NAME=ipt |
| | | |
| | | if [ -f ${PREFIX_PATH}/lib/libcjson.so ] ; then |
| | | msg_banner "$SRC_NAME already compile and installed" |
| | | return 0; |
| | | fi |
| | | |
| | | msg_banner "Start compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #wget https://github.com/downloads/libevent/libevent/${SRC_NAME}.${PACK_SUFIX} |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: decompress ${SRC_NAME} failure" |
| | | |
| | | cd ${SRC_NAME} |
| | | |
| | | make && sudo make install |
| | | check_result "ERROR: compile ${SRC_NAME} failure" |
| | | |
| | | cd - |
| | | } |
| | | |
| | | compile_cJSON |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | #+-------------------------------------------------------------------------------------------- |
| | | #|Description: This shell script used download and compile libevent for RaspberryPi |
| | | #| Author: GuoWenxue <guowenxue@gmail.com> |
| | | #| ChangeLog: |
| | | #| 1, Initialize 1.0.0 on 2021.04.12 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | PREFIX_PATH=/usr |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | function check_result() |
| | | { |
| | | if [ $? != 0 ] ; then |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | exit ; |
| | | fi |
| | | } |
| | | |
| | | function compile_libevent() |
| | | { |
| | | SRC_NAME=libevent-2.1.11-stable |
| | | PACK_SUFIX=tar.gz |
| | | IMG_NAME=ipt |
| | | |
| | | if [ -f ${PREFIX_PATH}/lib/libevent.so ] ; then |
| | | msg_banner "$SRC_NAME already compile and installed" |
| | | return 0; |
| | | fi |
| | | |
| | | msg_banner "Start compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #wget https://github.com/downloads/libevent/libevent/${SRC_NAME}.${PACK_SUFIX} |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: decompress ${SRC_NAME} failure" |
| | | |
| | | cd ${SRC_NAME} |
| | | |
| | | ./configure --prefix=${PREFIX_PATH} --enable-thread-support --enable-openssl --enable-function-sections |
| | | check_result "ERROR: configure ${SRC_NAME} failure" |
| | | |
| | | make && sudo make install |
| | | check_result "ERROR: compile ${SRC_NAME} failure" |
| | | |
| | | cd - |
| | | } |
| | | |
| | | compile_libevent |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | #+-------------------------------------------------------------------------------------------- |
| | | #|Description: This shell script used download and compile libgpiod for RaspberryPi |
| | | #| Author: GuoWenxue <guowenxue@gmail.com> |
| | | #| ChangeLog: |
| | | #| 1, Initialize 1.0.0 on 2021.04.12 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | PREFIX_PATH=/usr |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | function check_result() |
| | | { |
| | | if [ $? != 0 ] ; then |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | exit ; |
| | | fi |
| | | } |
| | | |
| | | function compile_libgpiod() |
| | | { |
| | | SRC_NAME=libgpiod-1.6.3 |
| | | PACK_SUFIX=tar.gz |
| | | |
| | | if [ -f ${PREFIX_PATH}/lib/libgpiod.so ] ; then |
| | | msg_banner "$SRC_NAME already compile and installed" |
| | | return 0; |
| | | fi |
| | | |
| | | msg_banner "Start compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #official site: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | cd ${SRC_NAME} |
| | | |
| | | ./autogen.sh && sudo ./configure --prefix=${PREFIX_PATH} --enable-tools |
| | | |
| | | make && sudo make install |
| | | |
| | | cd - |
| | | } |
| | | |
| | | compile_libgpiod |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | #+-------------------------------------------------------------------------------------------- |
| | | #|Description: This shell script used download and compile mosquitto for RaspberryPi |
| | | #| Author: GuoWenxue <guowenxue@gmail.com> |
| | | #| ChangeLog: |
| | | #| 1, Initialize 1.0.0 on 2011.04.12 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | PREFIX_PATH=/usr/ |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | function check_result() |
| | | { |
| | | if [ $? != 0 ] ; then |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | exit ; |
| | | fi |
| | | } |
| | | |
| | | function compile_mosquitto() |
| | | { |
| | | SRC_NAME=mosquitto-2.0.10 |
| | | PACK_SUFIX=tar.gz |
| | | |
| | | if [ -f ${PREFIX_PATH}/lib/libmosquitto.so ] ; then |
| | | msg_banner "$SRC_NAME already compile and installed" |
| | | return 0; |
| | | fi |
| | | |
| | | msg_banner "Start compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #wget https://mosquitto.org/files/source//${SRC_NAME}.${PACK_SUFIX} |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: decompress ${SRC_NAME} failure" |
| | | |
| | | cd ${SRC_NAME} |
| | | |
| | | sudo apt install -y libssl1.0-dev |
| | | |
| | | export DESTDIR=${PREFIX_PATH} |
| | | make WITH_SRV=no WITH_UUID=no |
| | | check_result "ERROR: compile ${SRC_NAME} failure" |
| | | |
| | | sudo make prefix=${PREFIX_PATH} install |
| | | } |
| | | |
| | | |
| | | compile_mosquitto |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | #+-------------------------------------------------------------------------------------------- |
| | | #|Description: This shell script used download and compile paho.mqtt for RaspberryPi |
| | | #| Author: GuoWenxue <guowenxue@gmail.com> |
| | | #| ChangeLog: |
| | | #| 1, Initialize 1.0.0 on 2011.04.12 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | PREFIX_PATH=/usr |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | function check_result() |
| | | { |
| | | if [ $? != 0 ] ; then |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | exit ; |
| | | fi |
| | | } |
| | | |
| | | function compile_paho() |
| | | { |
| | | SRC_NAME=paho.mqtt.c-1.3.9 |
| | | PACK_SUFIX=tar.gz |
| | | |
| | | if [ -f ${PREFIX_PATH}/lib/libpaho-mqtt3a.so ] ; then |
| | | msg_banner "$SRC_NAME already compile and installed" |
| | | return 0; |
| | | fi |
| | | |
| | | msg_banner "Start compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #wget https://github.com/eclipse/paho.mqtt.c/archive/v1.3.9.tar.gz -O ${SRC_NAME}.${PACK_SUFIX} |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: decompress ${SRC_NAME} failure" |
| | | |
| | | cd ${SRC_NAME} |
| | | |
| | | make && sudo make prefix=${PREFIX_PATH} install |
| | | |
| | | check_result "ERROR: compile ${SRC_NAME} failure" |
| | | |
| | | cd - |
| | | } |
| | | |
| | | compile_paho |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | #+-------------------------------------------------------------------------------------------- |
| | | #|Description: This shell script used download and compile pppd for RaspberryPi |
| | | #| Author: GuoWenxue <guowenxue@gmail.com> |
| | | #| ChangeLog: |
| | | #| 1, Initialize 1.0.0 on 2011.04.12 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | PREFIX_PATH=`pwd`/../install |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | function check_result() |
| | | { |
| | | if [ $? != 0 ] ; then |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | exit ; |
| | | fi |
| | | } |
| | | |
| | | function compile_pppd() |
| | | { |
| | | SRC_NAME=ppp-2.4.9 |
| | | PACK_SUFIX=tar.gz |
| | | |
| | | if [ -f ${PREFIX_PATH}//usr/local/sbin/pppd ] ; then |
| | | msg_banner "$SRC_NAME already compile and installed" |
| | | return 0; |
| | | fi |
| | | |
| | | msg_banner "Start cross compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #wget https://download.samba.org/pub/ppp/${SRC_NAME}.${PACK_SUFIX} |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | rm -rf ${SRC_NAME} |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: decompress ${SRC_NAME} failure" |
| | | |
| | | cd ${SRC_NAME} |
| | | |
| | | ./configure |
| | | sed -i -e 's|^FILTER=y.*|#FILTER=y|' pppd/Makefile |
| | | make && make install INSTROOT=${PREFIX_PATH} |
| | | |
| | | check_result "ERROR: compile ${SRC_NAME} failure" |
| | | |
| | | cd - |
| | | } |
| | | |
| | | |
| | | compile_pppd |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | ARCH=`uname -m` |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "| $1 " |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | echo ${ARCH} | grep "arm" > /dev/null |
| | | if [ $? == 0 ] ; then |
| | | msg_banner "Start local compile on RaspberryPi..." |
| | | cd arm && bash build.sh |
| | | exit 0; |
| | | fi |
| | | |
| | | echo ${ARCH} | grep "x86" > /dev/null |
| | | if [ $? == 0 ] ; then |
| | | msg_banner "Start cross compile on x86 server..." |
| | | cd x86 && bash build.sh |
| | | exit 0; |
| | | fi |
| | | |
| | | |
File was renamed from 3rdpart/appweb/build.sh |
| | |
| | | #| 1, Initialize 1.0.0 on 2011.04.12 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | CROSS_COMPILE=yes |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | PRJ_PATH=`pwd` |
| | | PREFIX_PATH=`pwd`/appweb |
| | | BOARD=RPI |
| | | PREFIX_PATH=${PRJ_PATH}/appweb |
| | | |
| | | BOARD=RPi |
| | | |
| | | mkdir -p $PREFIX_PATH/{bin,modules} |
| | | |
| | | if [ -z $CROSSTOOL ] ; then |
| | | CROSSTOOL=/opt/rpi/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf- |
| | | fi |
| | | CROSSTOOL=arm-linux-gnueabihf- |
| | | |
| | | function msg_banner() |
| | | { |
| | |
| | | export STRIP=${CROSSTOOL}strip |
| | | |
| | | # export cross configure |
| | | export CONFIG_CROSS=" --build=i686-pc-linux --host=arm-linux " |
| | | if [ "$CROSS_COMPILE" = "yes" ] ; then |
| | | export CONFIG_CROSS=" --build=x86_64-pc-linux --host=arm-linux " |
| | | fi |
| | | |
| | | # Clear LDFLAGS and CFLAGS |
| | | export LDFLAGS= |
| | |
| | | msg_banner "Start cross compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | wget http://museum.php.net/php5/${SRC_NAME}.${PACK_SUFIX} |
| | | #wget http://museum.php.net/php5/${SRC_NAME}.${PACK_SUFIX} |
| | | wget $LYFTP_SRC/$SRC_NAME.$PACK_SUFIX |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | |
| | | function compile_appweb() |
| | | { |
| | | SRC_NAME=appweb-3.4.2 |
| | | PACK_SUFIX=-0-src.tgz |
| | | PACK_SUFIX=tar.gz |
| | | |
| | | if [ -f ${PREFIX_PATH}/bin/appweb ] ; then |
| | | return 0; |
| | |
| | | |
| | | msg_banner "Start cross compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}${PACK_SUFIX} ] ; then |
| | | wget https://embedthis.com/software/${SRC_NAME}${PACK_SUFIX} |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #wget https://embedthis.com/software/${SRC_NAME}${PACK_SUFIX} |
| | | wget $LYFTP_SRC/$SRC_NAME.$PACK_SUFIX |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xzf ${SRC_NAME}${PACK_SUFIX} |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | cd ${SRC_NAME} |
| | | |
| | | ./configure --prefix=${PREFIX_PATH} ${CONFIG_CROSS} --type=RELEASE --static --port=80 --enable-assert \ |
| | |
| | | |
| | | function install_appweb() |
| | | { |
| | | SCRIPTS=s80Appweb |
| | | msg_banner "Start install webserver appweb " |
| | | |
| | | cd ${PRJ_PATH} |
| | | |
| | | # install web page |
| | | rm -rf $PREFIX_PATH/web |
| | | cp -rf web $PREFIX_PATH |
| | | if [ -f web.tar.gz ] ; then |
| | | tar -xzf web.tar.gz -C $PREFIX_PATH |
| | | fi |
| | | |
| | | sed -i -e "s|^Listen 4100|Listen 80|g" $PREFIX_PATH/appweb.conf |
| | | sed -i -e "s|^Listen 4100|Listen 5000|g" $PREFIX_PATH/appweb.conf |
| | | sed -i -e "s|^DirectoryIndex.*|DirectoryIndex index.php|g" $PREFIX_PATH/appweb.conf |
| | | sed -i -e 's|^LoadModulePath "../modules"|LoadModulePath "./modules"|g' $PREFIX_PATH/appweb.conf |
| | | |
| | | set -x |
| | | |
| | | cat << EOF > run.sh |
| | | cat << 'EOF' > ${SCRIPTS} |
| | | #!/bin/sh |
| | | APPWEB_PATH=/apps/appweb |
| | | export LD_LIBRARY_PATH=\${LD_LIBRARY_PATH}:\${APPWEB_PATH}/modules |
| | | cd \${APPWEB_PATH} |
| | | ./bin/appweb --config appweb.conf & |
| | | # |
| | | # Start/stop appweb |
| | | # |
| | | |
| | | APP_NAME=appweb |
| | | |
| | | WORK_PATH=/apps/appweb |
| | | |
| | | DAEMON=${WORK_PATH}/bin/appweb |
| | | CONFIG=${WORK_PATH}/appweb.conf |
| | | PIDFILE=/tmp/${APP_NAME}.pid |
| | | |
| | | export PATH=${PATH}:${WORK_PATH}/bin |
| | | export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${WORK_PATH}/modules |
| | | cd ${WORK_PATH} |
| | | |
| | | [ -f $CONFIG ] || exit 0 |
| | | |
| | | case "$1" in |
| | | start) |
| | | echo "Starting ${APP_NAME}..." |
| | | start-stop-daemon -S -b -m -x "$DAEMON" -p "$PIDFILE" -- --config "$CONFIG" |
| | | ;; |
| | | stop) |
| | | echo "Stopping ${APP_NAME}..." |
| | | start-stop-daemon -K -x "$DAEMON" -p "$PIDFILE" -o |
| | | ;; |
| | | restart) |
| | | "$0" stop |
| | | sleep 1 # Prevent race condition: ensure dhcpcd stops before start. |
| | | "$0" start |
| | | ;; |
| | | *) |
| | | echo "Usage: $0 {start|stop|restart}" |
| | | exit 1 |
| | | esac |
| | | |
| | | EOF |
| | | |
| | | chmod 755 run.sh |
| | | mv run.sh $PREFIX_PATH/ |
| | | chmod 755 ${SCRIPTS} |
| | | mv ${SCRIPTS} $PREFIX_PATH/ |
| | | |
| | | tar -czf appweb_${BOARD}.tar.gz `basename $PREFIX_PATH` |
| | | ls -l appweb_${BOARD}.tar.gz |
| | | tar -czf appweb-${BOARD}.tar.gz `basename $PREFIX_PATH` |
| | | ls -l appweb-${BOARD}.tar.gz |
| | | } |
| | | |
| | | |
| | | if [[ $# == 1 ]] && [[ $1 == "clean" ]] ; then |
| | | rm -rf appweb* |
| | | rm -rf php* |
| | | exit; |
| | | fi |
| | | |
| | | export_cross |
| | | |
| | | compile_php |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | CROSSTOOL=arm-linux-gnueabihf- |
| | | |
| | | # display in red |
| | | function pr_error() { |
| | | echo "" |
| | | echo -e "\033[40;31m --E-- $1 \033[0m" |
| | | echo "" |
| | | } |
| | | |
| | | # display in yellow |
| | | function pr_warn() { |
| | | echo "" |
| | | echo -e "\033[40;33m --W-- $1 \033[0m" |
| | | echo "" |
| | | } |
| | | |
| | | # display in green |
| | | function pr_info() { |
| | | echo -e "\033[40;32m --I-- $1 \033[0m" |
| | | } |
| | | |
| | | function check_depend() |
| | | { |
| | | ARCH=`uname -m` |
| | | echo ${ARCH} | grep "x86" > /dev/null |
| | | if [ $? != 0 ] ; then |
| | | pr_error "This folder must compile on X86 server "; |
| | | exit 1; |
| | | fi |
| | | |
| | | |
| | | ${CROSSTOOL}g++ -v > /dev/null 2>&1 |
| | | if [ $? != 0 ] ; then |
| | | pr_error "Crosstool not installed, please install it by follow command:" |
| | | pr_info "sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf" |
| | | exit 1; |
| | | fi |
| | | } |
| | | |
| | | function do_compile |
| | | { |
| | | for dir in `ls` |
| | | do |
| | | if [ -f $dir/build*.sh ] ; then |
| | | cd $dir |
| | | bash ./build*.sh |
| | | cd - |
| | | fi |
| | | done |
| | | } |
| | | |
| | | function do_clean |
| | | { |
| | | for dir in `ls` |
| | | do |
| | | if [ -f $dir/build*.sh ] ; then |
| | | cd $dir |
| | | bash ./build*.sh clean |
| | | cd - |
| | | fi |
| | | done |
| | | |
| | | rm -rf install |
| | | } |
| | | |
| | | if [[ $# == 1 ]] && [[ $1 == "clean" ]] ; then |
| | | do_clean |
| | | exit; |
| | | fi |
| | | |
| | | check_depend |
| | | |
| | | do_compile |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | #+-------------------------------------------------------------------------------------------- |
| | | #|Description: This shell script used download and compile cJSON for RaspberryPi |
| | | #| Author: GuoWenxue <guowenxue@gmail.com> |
| | | #| ChangeLog: |
| | | #| 1, Initialize 1.0.0 on 2022.04.10 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | JOBS=`cat /proc/cpuinfo |grep "processor"|wc -l` |
| | | |
| | | PRJ_PATH=`pwd` |
| | | LIBS_PATH=$PRJ_PATH/../install |
| | | |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | CROSSTOOL=arm-linux-gnueabihf- |
| | | |
| | | # display in red |
| | | function pr_error() { |
| | | echo -e "\033[40;31m --E-- $1 \033[0m" |
| | | } |
| | | |
| | | # display in yellow |
| | | function pr_warn() { |
| | | echo -e "\033[40;33m --W-- $1 \033[0m" |
| | | } |
| | | |
| | | # display in green |
| | | function pr_info() { |
| | | echo -e "\033[40;32m --I-- $1 \033[0m" |
| | | } |
| | | |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo -e "|\033[40;33m $1 \033[0m" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | function check_result() |
| | | { |
| | | if [ $? != 0 ] ; then |
| | | pr_error $1 |
| | | fi |
| | | } |
| | | |
| | | |
| | | function compile_cjson() |
| | | { |
| | | SRC_NAME=cJSON-1.7.15 |
| | | PACK_SUFIX=tar.gz |
| | | |
| | | if [ -f ${LIBS_PATH}/lib/libcjson.so ] ; then |
| | | msg_banner "$SRC_NAME already compile and installed" |
| | | return 0; |
| | | fi |
| | | |
| | | msg_banner "Start compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #wget https://mosquitto.org/files/source//${SRC_NAME}.${PACK_SUFIX} |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: decompress ${SRC_NAME} failure" |
| | | |
| | | cd ${SRC_NAME} |
| | | |
| | | sed -i "s|^CC =.*|CC = ${CROSSTOOL}gcc -std=c89|" Makefile |
| | | |
| | | make && make PREFIX=${LIBS_PATH} install |
| | | } |
| | | |
| | | |
| | | compile_cjson |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | #+-------------------------------------------------------------------------------------------- |
| | | #|Description: This shell script used download and compile mosquitto for RaspberryPi |
| | | #| Author: GuoWenxue <guowenxue@gmail.com> |
| | | #| ChangeLog: |
| | | #| 1, Initialize 1.0.0 on 2011.04.12 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | JOBS=`cat /proc/cpuinfo |grep "processor"|wc -l` |
| | | |
| | | PRJ_PATH=`pwd` |
| | | LIBS_PATH=$PRJ_PATH/../install |
| | | |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | |
| | | CROSSTOOL=arm-linux-gnueabihf- |
| | | |
| | | # display in red |
| | | function pr_error() { |
| | | echo -e "\033[40;31m --E-- $1 \033[0m" |
| | | } |
| | | |
| | | # display in yellow |
| | | function pr_warn() { |
| | | echo -e "\033[40;33m --W-- $1 \033[0m" |
| | | } |
| | | |
| | | # display in green |
| | | function pr_info() { |
| | | echo -e "\033[40;32m --I-- $1 \033[0m" |
| | | } |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo -e "|\033[40;33m $1 \033[0m" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | function check_result() |
| | | { |
| | | if [ $? != 0 ] ; then |
| | | pr_error $1 |
| | | fi |
| | | } |
| | | |
| | | |
| | | function compile_mosquitto() |
| | | { |
| | | SRC_NAME=mosquitto-2.0.14 |
| | | PACK_SUFIX=tar.gz |
| | | |
| | | if [ -f ${LIBS_PATH}/lib/libmosquitto.so ] ; then |
| | | msg_banner "$SRC_NAME already compile and installed" |
| | | return 0; |
| | | fi |
| | | |
| | | msg_banner "Start compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #wget https://mosquitto.org/files/source//${SRC_NAME}.${PACK_SUFIX} |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: decompress ${SRC_NAME} failure" |
| | | |
| | | cd ${SRC_NAME} |
| | | SRC_PATH=`pwd` |
| | | |
| | | export CROSS_COMPILE=${CROSSTOOL} |
| | | export CC=gcc |
| | | |
| | | make -j ${JOBS} LIB_LDFLAGS="-L${LIBS_PATH}/lib" LOCAL_LDFLAGS+="-L${LIBS_PATH}/lib" \ |
| | | LIB_CPPFLAGS+="-I ${LIBS_PATH}/include -I${SRC_PATH} -I${SRC_PATH}/src -I${SRC_PATH}/include" \ |
| | | LIB_CPPFLAGS+="-I${SRC_PATH}/lib -I${SRC_PATH}/lib/cpp -I${SRC_PATH}/deps" \ |
| | | LOCAL_CPPFLAGS+="-I ${LIBS_PATH}/include -I${SRC_PATH}/src -I${SRC_PATH}/apps/mosquitto_passwd/ -DVERSION=\\\"\"2.0.14\\\"\" " \ |
| | | APP_CFLAGS+="-I ${LIBS_PATH}/include -I${SRC_PATH}/src" APP_LDFLAGS="-L ${LIBS_PATH}/lib" \ |
| | | CLIENT_CFLAGS="-I ${LIBS_PATH}/include -I${SRC_PATH} -I${SRC_PATH}/include -DVERSION=\\\"\"2.0.14\\\"\" " \ |
| | | CLIENT_LDFLAGS="-L ${LIBS_PATH}/lib" PLUGIN_LDFLAGS="-L ${LIBS_PATH}/lib" BROKER_LDFLAGS="-L ${LIBS_PATH}/lib" |
| | | |
| | | check_result "ERROR: compile ${SRC_NAME} failure" |
| | | |
| | | make DESTDIR=${LIBS_PATH} install |
| | | check_result "ERROR: install ${SRC_NAME} failure" |
| | | } |
| | | |
| | | # compile cjson first |
| | | cd ../cjson && ./build.sh && cd ${PRJ_PATH} |
| | | cd ../openssl && ./build.sh && cd ${PRJ_PATH} |
| | | |
| | | compile_mosquitto |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | #+-------------------------------------------------------------------------------------------- |
| | | #|Description: This shell script used download and compile openssl for ARM |
| | | #| Author: GuoWenxue <guowenxue@gmail.com> |
| | | #| ChangeLog: |
| | | #| 1, Initialize 1.0.0 on 2011.04.12 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | JOBS=`cat /proc/cpuinfo |grep "processor"|wc -l` |
| | | |
| | | PRJ_PATH=`pwd` |
| | | PREFIX_PATH=`pwd`/../install |
| | | |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | CROSSTOOL=arm-linux-gnueabihf- |
| | | |
| | | # display in red |
| | | function pr_error() { |
| | | echo -e "\033[40;31m --E-- $1 \033[0m" |
| | | } |
| | | |
| | | # display in yellow |
| | | function pr_warn() { |
| | | echo -e "\033[40;33m --W-- $1 \033[0m" |
| | | } |
| | | |
| | | # display in green |
| | | function pr_info() { |
| | | echo -e "\033[40;32m --I-- $1 \033[0m" |
| | | } |
| | | |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo -e "|\033[40;33m $1 \033[0m" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | function check_result() |
| | | { |
| | | if [ $? != 0 ] ; then |
| | | pr_error $1 |
| | | fi |
| | | } |
| | | |
| | | |
| | | function export_cross() |
| | | { |
| | | # export cross toolchain |
| | | export CC=${CROSSTOOL}gcc |
| | | export AS=${CROSSTOOL}as |
| | | export AR=${CROSSTOOL}ar |
| | | export LD=${CROSSTOOL}ld |
| | | export NM=${CROSSTOOL}nm |
| | | export RANLIB=${CROSSTOOL}ranlib |
| | | export OBJDUMP=${CROSSTOOL}objdump |
| | | export STRIP=${CROSSTOOL}strip |
| | | |
| | | # export cross configure |
| | | export CONFIG_CROSS=" --build=i686-pc-linux --host=arm-linux " |
| | | |
| | | # Clear LDFLAGS and CFLAGS |
| | | export LDFLAGS= |
| | | export CFLAGS= |
| | | } |
| | | |
| | | function compile_openssl() |
| | | { |
| | | SRC_NAME=openssl-1.1.1n |
| | | PACK_SUFIX=tar.gz |
| | | |
| | | if [ -f ${PREFIX_PATH}/lib/libcrypto.a ] ; then |
| | | msg_banner "$SRC_NAME already compile and installed" |
| | | return 0; |
| | | fi |
| | | |
| | | msg_banner "Start cross compile $SRC_NAME " |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #wget https://www.openssl.org/source/${SRC_NAME}.${PACK_SUFIX} |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "ERROR: download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | cd ${SRC_NAME} |
| | | |
| | | CROSS_COMPILE=${CROSSTOOL} CFLAGS=-I${PRJ_PATH}/cryptodev-linux ./Configure \ |
| | | threads -shared -no-zlib --prefix=$PREFIX_PATH --openssldir=$PREFIX_PATH \ |
| | | linux-armv4 |
| | | |
| | | make -j ${JOBS} && make install |
| | | check_result "ERROR: compile ${SRC_NAME} failure" |
| | | |
| | | cd - |
| | | } |
| | | |
| | | compile_openssl |
| | | |
| | | |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | #+-------------------------------------------------------------------------------------------- |
| | | #|Description: This shell script used download and compile QT5 for ARM |
| | | #| Author: GuoWenxue <guowenxue@gmail.com> |
| | | #| |
| | | #| WARNNING: QT >= 5.7 need crosstool g++ support C++11 support |
| | | #| QT configure need host g++ support C++11, so need config g++ on ubuntu host: |
| | | #| sudo update-alternatives --config g++ |
| | | #| |
| | | #| ChangeLog: |
| | | #| 1, Initialize 1.0.0 on 2011.04.12 |
| | | #+-------------------------------------------------------------------------------------------- |
| | | |
| | | JOBS=`cat /proc/cpuinfo |grep "processor"|wc -l` |
| | | |
| | | PRJ_PATH=`pwd` |
| | | LIBS_PATH=$PRJ_PATH/install |
| | | |
| | | QT_INST_PATH=/apps/qt5_rpi |
| | | |
| | | # sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf |
| | | CROSSTOOL=arm-linux-gnueabihf- |
| | | |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | # display in red |
| | | function pr_error() { |
| | | echo -e "\033[40;31m --E-- $1 \033[0m" |
| | | } |
| | | |
| | | # display in yellow |
| | | function pr_warn() { |
| | | echo -e "\033[40;33m --W-- $1 \033[0m" |
| | | } |
| | | |
| | | # display in green |
| | | function pr_info() { |
| | | echo -e "\033[40;32m --I-- $1 \033[0m" |
| | | } |
| | | |
| | | function msg_banner() |
| | | { |
| | | echo "" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo -e "|\033[40;33m $1 \033[0m" |
| | | echo "+-----------------------------------------------------------------------" |
| | | echo "" |
| | | } |
| | | |
| | | function check_result() |
| | | { |
| | | if [ $? != 0 ] ; then |
| | | pr_error $1 |
| | | fi |
| | | } |
| | | |
| | | function compile_qt5() |
| | | { |
| | | # 5.6.3 is the last version can be compiled by g++ without c++11 support |
| | | SRC_NAME=qt-everywhere-opensource-src-5.6.3 |
| | | |
| | | PACK_SUFIX=tar.xz |
| | | |
| | | #rm -rf ${QT_INST_PATH}/lib/libQt5Gui.so |
| | | if [ -f ${QT_INST_PATH}/lib/libQt5Gui.so ] ; then |
| | | msg_banner "Already cross compile $SRC_NAME " |
| | | return 0; |
| | | fi |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | msg_banner "Start download ${SRC_NAME}.${PACK_SUFIX} " |
| | | wget ${LYFTP_SRC}/qt/${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | msg_banner "Start decompress $SRC_NAME.${PACK_SUFIX} and patch" |
| | | if [ ! -d ${SRC_NAME} ] ; then |
| | | tar -xJf ${SRC_NAME}.${PACK_SUFIX} |
| | | patch -p0 < patch/${SRC_NAME}.patch |
| | | fi |
| | | |
| | | cd ${SRC_NAME} |
| | | |
| | | QMAKE_FILE=qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf |
| | | |
| | | grep "`basename ${CROSSTOOL}`" ${QMAKE_FILE} > /dev/null 2>&1 |
| | | if [ $? != 0 ] ; then |
| | | sed -i "s|arm-linux-gnueabi-|$CROSSTOOL|" ${QMAKE_FILE} |
| | | fi |
| | | |
| | | ./configure -opensource -confirm-license -release -shared -strip -no-c++11 \ |
| | | -prefix ${QT_INST_PATH} -xplatform linux-arm-gnueabi-g++ -make libs \ |
| | | -no-cups -no-libproxy -no-avx -no-mtdev -no-rpath -no-glib -no-xcb -pch \ |
| | | -no-eglfs -no-opengl -no-openssl -no-separate-debug-info -nomake tests \ |
| | | -qt-freetype -qt-zlib -qt-libpng -qt-libjpeg -tslib -linuxfb -qpa linuxfb \ |
| | | -I${LIBS_PATH}/include/ -L${LIBS_PATH}/lib/ -I${QT_INST_PATH}/include/ -L${QT_INST_PATH}/lib/ |
| | | |
| | | msg_banner "Start cross compile $SRC_NAME " |
| | | make -j${JOBS} && make install |
| | | check_result "compile ${SRC_NAME} failure" |
| | | cp ./qtbase/plugins/platforms/libqlinuxfb.so ${QT_INST_PATH}/lib |
| | | cp -af ${LIBS_PATH}/lib/libts*so* ${QT_INST_PATH}/lib |
| | | |
| | | cd - |
| | | } |
| | | |
| | | function compile_tslib() |
| | | { |
| | | SRC_NAME=tslib-1.22 |
| | | PACK_SUFIX=tar.bz2 |
| | | |
| | | |
| | | if [ -f ${LIBS_PATH}/lib/libts.so ] ; then |
| | | msg_banner "Already cross compile $SRC_NAME " |
| | | return 0; |
| | | fi |
| | | |
| | | mkdir -p libs && cd libs |
| | | |
| | | msg_banner "Start cross compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #tslib official download address: https://github.com/libts/tslib/tags |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xjf ${SRC_NAME}.${PACK_SUFIX} |
| | | cd ${SRC_NAME} |
| | | |
| | | ./configure --prefix=${LIBS_PATH} ${CONFIG_CROSS} |
| | | make && make install |
| | | |
| | | cd ${PRJ_PATH} |
| | | } |
| | | |
| | | function compile_libiconv() |
| | | { |
| | | SRC_NAME=libiconv-1.15 |
| | | PACK_SUFIX=tar.gz |
| | | |
| | | if [ -f ${LIBS_PATH}/lib/libiconv.so ] ; then |
| | | msg_banner "Already cross compile $SRC_NAME " |
| | | return 0; |
| | | fi |
| | | |
| | | mkdir -p libs && cd libs |
| | | |
| | | msg_banner "Start cross compile $SRC_NAME " |
| | | |
| | | if [ ! -f ${SRC_NAME}.${PACK_SUFIX} ] ; then |
| | | #wget https://ftp.gnu.org/gnu/libiconv/${SRC_NAME}.${PACK_SUFIX} |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.${PACK_SUFIX} |
| | | check_result "download ${SRC_NAME} failure" |
| | | fi |
| | | |
| | | tar -xzf ${SRC_NAME}.${PACK_SUFIX} |
| | | cd ${SRC_NAME} |
| | | |
| | | ./configure --prefix=${LIBS_PATH} ${CONFIG_CROSS} |
| | | make && make install |
| | | |
| | | cd ${PRJ_PATH} |
| | | } |
| | | |
| | | |
| | | function export_cross() |
| | | { |
| | | # export cross toolchain |
| | | export CC=${CROSSTOOL}gcc |
| | | export AS=${CROSSTOOL}as |
| | | export AR=${CROSSTOOL}ar |
| | | export LD=${CROSSTOOL}ld |
| | | export NM=${CROSSTOOL}nm |
| | | export RANLIB=${CROSSTOOL}ranlib |
| | | export OBJDUMP=${CROSSTOOL}objdump |
| | | export STRIP=${CROSSTOOL}strip |
| | | |
| | | # export cross configure |
| | | export CONFIG_CROSS=" --build=i686-pc-linux --host=arm-linux " |
| | | |
| | | # Clear LDFLAGS and CFLAGS |
| | | export LDFLAGS= |
| | | export CFLAGS= |
| | | } |
| | | |
| | | function unexport_cross() |
| | | { |
| | | # export cross toolchain |
| | | export CC="" |
| | | export AS="" |
| | | export AR="" |
| | | export LD="" |
| | | export NM="" |
| | | export RANLIB="" |
| | | export OBJDUMP="" |
| | | export STRIP="" |
| | | |
| | | # export cross configure |
| | | export CONFIG_CROSS="" |
| | | |
| | | # Clear LDFLAGS and CFLAGS |
| | | export LDFLAGS="" |
| | | export CFLAGS="" |
| | | } |
| | | |
| | | function check_deptool() |
| | | { |
| | | ${CROSSTOOL}g++ -v > /dev/null 2>&1 |
| | | if [ $? != 0 ] ; then |
| | | echo "" |
| | | pr_error "Crosstool not installed, please install it by follow command:" |
| | | pr_info "sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf" |
| | | echo "" |
| | | exit 1; |
| | | fi |
| | | } |
| | | |
| | | check_deptool |
| | | |
| | | export_cross |
| | | |
| | | compile_libiconv |
| | | |
| | | compile_tslib |
| | | |
| | | unexport_cross |
| | | |
| | | compile_qt5 |
| | | |
New file |
| | |
| | | import QtQuick 2.5
|
| | |
|
| | | Rectangle {
|
| | | property alias mouseArea: mouseArea
|
| | |
|
| | | width: 360
|
| | | height: 360
|
| | |
|
| | | MouseArea {
|
| | | id: mouseArea
|
| | | anchors.fill: parent
|
| | | }
|
| | |
|
| | | Text {
|
| | | anchors.centerIn: parent
|
| | | text: "Hello World"
|
| | | }
|
| | | }
|
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | # export qmake command path |
| | | export PATH=$PATH:/apps/qt5_rpi/bin/ |
| | | |
| | | # project name is current working directory name |
| | | PRJ_NAME=$(basename `pwd`) |
| | | |
| | | # generate project file |
| | | rm -f ${PRJ_NAME}.pro |
| | | qmake -project |
| | | |
| | | # Add qml support to fix bug: QQmlApplicationEngine: No such file or directory |
| | | echo "QT += qml" >> ${PRJ_NAME}.pro |
| | | |
| | | # generate makefile |
| | | qmake -makefile ${PRJ_NAME}.pro |
| | | |
| | | |
| | | # start to cross compile |
| | | make && make clean |
| | | |
New file |
| | |
| | | #include <QGuiApplication>
|
| | | #include <QQmlApplicationEngine>
|
| | |
|
| | | int main(int argc, char *argv[])
|
| | | {
|
| | | QGuiApplication app(argc, argv);
|
| | |
|
| | | QQmlApplicationEngine engine;
|
| | | engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
|
| | |
|
| | | return app.exec();
|
| | | }
|
New file |
| | |
| | | import QtQuick 2.5
|
| | | import QtQuick.Window 2.2
|
| | |
|
| | | Window {
|
| | | visible: true
|
| | | width: 640
|
| | | height: 480
|
| | | title: qsTr("Hello World")
|
| | |
|
| | | MainForm {
|
| | | anchors.fill: parent
|
| | | mouseArea.onClicked: {
|
| | | Qt.quit();
|
| | | }
|
| | |
|
| | | Text {
|
| | | id: text1
|
| | | x: 131
|
| | | y: 136
|
| | | width: 100
|
| | | height: 20
|
| | | text: "192.168.1.10"
|
| | | font.pixelSize: 12
|
| | | }
|
| | |
|
| | | TextInput {
|
| | | id: textInput1
|
| | | x: 45
|
| | | y: 136
|
| | | width: 80
|
| | | height: 20
|
| | | text: "IP地址"
|
| | | font.pixelSize: 12
|
| | | }
|
| | |
|
| | | TextEdit {
|
| | | id: textEdit1
|
| | | x: 261
|
| | | y: 136
|
| | | width: 80
|
| | | height: 20
|
| | | text: qsTr("Text Edit")
|
| | | font.pixelSize: 12
|
| | | }
|
| | |
|
| | | Rectangle {
|
| | | id: rectangle1
|
| | | x: 380
|
| | | y: 165
|
| | | width: 200
|
| | | height: 200
|
| | | color: "#ffffff"
|
| | | }
|
| | |
|
| | | Image {
|
| | | id: image1
|
| | | x: 25
|
| | | y: 245
|
| | | width: 100
|
| | | height: 100
|
| | | source: "qrc:/qtquickplugin/images/template_image.png"
|
| | | }
|
| | |
|
| | | Item {
|
| | | id: item1
|
| | | x: 149
|
| | | y: 187
|
| | | width: 200
|
| | | height: 200
|
| | | }
|
| | |
|
| | | MainForm {
|
| | | id: mainForm1
|
| | | x: 163
|
| | | y: 52
|
| | | }
|
| | | }
|
| | | }
|
New file |
| | |
| | | <RCC>
|
| | | <qresource prefix="/">
|
| | | <file>main.qml</file>
|
| | | <file>MainForm.ui.qml</file>
|
| | | </qresource>
|
| | | </RCC>
|
New file |
| | |
| | | diff -Nuar qt-everywhere-opensource-src-5.6.3/qtserialbus/src/plugins/canbus/socketcan/socketcanbackend.cpp qt-everywhere-opensource-src-5.6.3-modify/qtserialbus/src/plugins/canbus/socketcan/socketcanbackend.cpp |
| | | --- qt-everywhere-opensource-src-5.6.3/qtserialbus/src/plugins/canbus/socketcan/socketcanbackend.cpp 2017-09-06 20:16:43.000000000 +0800 |
| | | +++ qt-everywhere-opensource-src-5.6.3-modify/qtserialbus/src/plugins/canbus/socketcan/socketcanbackend.cpp 2022-04-08 00:26:20.441520428 +0800 |
| | | @@ -42,6 +42,7 @@ |
| | | |
| | | #include <linux/can/error.h> |
| | | #include <linux/can/raw.h> |
| | | +#include <linux/sockios.h> |
| | | #include <errno.h> |
| | | #include <unistd.h> |
| | | #include <net/if.h> |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2018 LingYun IoT System Studio |
| | | * Copyright: (C) 2022 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: ds18b20.c |
| | | * Description: This file is temperature sensor DS18B20 code |
| | | * Description: This file is DS18B20 temperature sensor example source code. |
| | | * |
| | | * Version: 1.0.0(2018/10/14) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | |
| | | return 1; |
| | | } |
| | | |
| | | printf("DS19B20 get temperature: %f ℃\n", temp); |
| | | printf("DS18B20 get temperature: %f 'C\n", temp); |
| | | return 0; |
| | | } |
| | | |
| | |
| | | |
| | | int ds18b20_get_temperature(float *temp) |
| | | { |
| | | char w1_path[50] = "/sys/bus/w1/devices/"; |
| | | const char *w1_path = "/sys/bus/w1/devices/"; |
| | | char ds_path[50]; |
| | | char chip[20]; |
| | | char buf[128]; |
| | | DIR *dirp; |
| | | struct dirent *direntp; |
| | | int fd =-1; |
| | | char *ptr; |
| | | float value; |
| | | int found = 0; |
| | | int rv = 0; |
| | | |
| | | if( !temp ) |
| | | { |
| | |
| | | } |
| | | |
| | | /* get DS18B20 sample file full path: /sys/bus/w1/devices/28-xxxx/w1_slave */ |
| | | strncat(w1_path, chip, sizeof(w1_path)-strlen(w1_path)); |
| | | strncat(w1_path, "/w1_slave", sizeof(w1_path)-strlen(w1_path)); |
| | | snprintf(ds_path, sizeof(ds_path), "%s/%s/w1_slave", w1_path, chip); |
| | | |
| | | /* open file /sys/bus/w1/devices/28-xxxx/w1_slave to get temperature */ |
| | | if( (fd=open(w1_path, O_RDONLY)) < 0 ) |
| | | if( (fd=open(ds_path, O_RDONLY)) < 0 ) |
| | | { |
| | | printf("open %s error: %s\n", w1_path, strerror(errno)); |
| | | printf("open %s error: %s\n", ds_path, strerror(errno)); |
| | | return -4; |
| | | } |
| | | |
| | | if(read(fd, buf, sizeof(buf)) < 0) |
| | | { |
| | | printf("read %s error: %s\n", w1_path, strerror(errno)); |
| | | return -5; |
| | | printf("read %s error: %s\n", ds_path, strerror(errno)); |
| | | rv = -5; |
| | | goto cleanup; |
| | | } |
| | | |
| | | ptr = strstr(buf, "t="); |
| | | if( !ptr ) |
| | | { |
| | | printf("ERROR: Can not get temperature\n"); |
| | | return -6; |
| | | rv = -6; |
| | | goto cleanup; |
| | | } |
| | | |
| | | ptr+=2; |
| | |
| | | /* convert string value to float value */ |
| | | *temp = atof(ptr)/1000; |
| | | |
| | | cleanup: |
| | | close(fd); |
| | | |
| | | return 0; |
| | | return rv; |
| | | } |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | make |
| | | ./main/client_main -i 127.0.0.1 -p 8888 -I 30 -d |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | # libraries install path |
| | | INST_PATH=`pwd`/../install |
| | | |
| | | # LingYun studio FTP server address for all the open source code |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | # set shell script exit when any command failure |
| | | set -e |
| | | |
| | | # funciton used to build cjson source code |
| | | function build_cjson() |
| | | { |
| | | SRC_NAME=cJSON-1.7.15 |
| | | |
| | | if [ -L $INST_PATH/lib/libcjson.so ] ; then |
| | | echo "$SRC_NAME already compile and installed" |
| | | return ; |
| | | fi |
| | | |
| | | # If source code tarball file not exist, it will download the packet. |
| | | if [ ! -f ${SRC_NAME}.tar.gz ] ; then |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.tar.gz |
| | | fi |
| | | |
| | | |
| | | # If source code folder not exist, decompress the tarball packet |
| | | if [ ! -d ${SRC_NAME} ] ; then |
| | | tar -xzf ${SRC_NAME}.tar.gz |
| | | fi |
| | | |
| | | cd ${SRC_NAME} |
| | | |
| | | make && make DESTDIR=${INST_PATH} PREFIX=/ install |
| | | |
| | | cd - |
| | | } |
| | | |
| | | # start build cjson |
| | | |
| | | build_cjson |
New file |
| | |
| | | all: |
| | | cd sqlite && ./build.sh |
| | | cd cjson && ./build.sh |
| | | |
| | | clean: |
| | | cd sqlite && rm -rf sqlite* |
| | | cd cjson && rm -rf c* |
| | | |
| | | distclean: clean |
| | | rm -rf install |
New file |
| | |
| | | #!/bin/bash |
| | | |
| | | # library install path |
| | | INST_PATH=`pwd`/../install |
| | | |
| | | # LingYun studio FTP server address for all the open source code |
| | | LYFTP_SRC=ftp://master.iot-yun.club/src/ |
| | | |
| | | # set shell script exit when any command failure |
| | | set -e |
| | | |
| | | #define a funciton to build sqlite source code |
| | | function build_sqlite() |
| | | { |
| | | SRC_NAME=sqlite-autoconf-3380200 |
| | | |
| | | if [ -L $INST_PATH/lib/libsqlite3.so ] ; then |
| | | echo "$SRC_NAME already compile and installed" |
| | | return ; |
| | | fi |
| | | |
| | | # If source code tarball file not exist, it will download the packet. |
| | | if [ ! -f ${SRC_NAME}.tar.gz ] ; then |
| | | #wget https://sqlite.org/2022/${SRC_NAME}.tar.gz |
| | | wget ${LYFTP_SRC}/${SRC_NAME}.tar.gz |
| | | fi |
| | | |
| | | |
| | | # If source code folder not exist, decompress the tarball packet |
| | | if [ ! -d ${SRC_NAME} ] ; then |
| | | tar -xzf ${SRC_NAME}.tar.gz |
| | | fi |
| | | |
| | | cd ${SRC_NAME} |
| | | |
| | | ./configure --prefix=${INST_PATH} --enable-static |
| | | |
| | | make && make install |
| | | } |
| | | |
| | | |
| | | # call function to start build sqlite |
| | | |
| | | build_sqlite |
New file |
| | |
| | | #include <stdio.h> |
| | | #include <errno.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | #include <sys/types.h> |
| | | #include <sys/socket.h> |
| | | #include <arpa/inet.h> |
| | | #include <stdlib.h> |
| | | #include <getopt.h> |
| | | #include <time.h> |
| | | |
| | | #include "logger.h" |
| | | #include "ds18b20.h" |
| | | #include "packet.h" |
| | | #include "socket.h" |
| | | #include "sqlite_blob.h" |
| | | #include "util_proc.h" |
| | | #include "util_time.h" |
| | | |
| | | |
| | | void print_usage(char *progname) |
| | | { |
| | | printf("%s usage: \n", progname); |
| | | printf("-i(--ipaddr) : sepcify server IP address\n"); |
| | | printf("-p(--port) : sepcify server port.\n"); |
| | | printf("-I(--interval): sepcify report interval time\n"); |
| | | printf("-s(--sn) : sepcify device serial number\n"); |
| | | printf("-d(--debug) : run as debug mode\n"); |
| | | printf("-h(--Help) : print this help information.\n"); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | static int check_sample_time(time_t *last_time, int interval); |
| | | |
| | | int main(int argc, char **argv) |
| | | { |
| | | int rv = -1; |
| | | int port; |
| | | char *serverip; |
| | | int interval = 30; /* default report termperature every 30 seconds */ |
| | | int sn = 1; /* default serial number for device ID */ |
| | | int debug = 0; /* running in debug mode or not */ |
| | | int loglevel = LOG_LEVEL_INFO; |
| | | char *logfile="client.log"; |
| | | |
| | | socket_ctx_t sock; |
| | | time_t last_time = 0; |
| | | int sample_flag = 0; |
| | | |
| | | char pack_buf[1024]; |
| | | int pack_bytes; |
| | | pack_info_t pack_info; |
| | | pack_proc_t pack_proc = packet_segmented_pack; /* use string packet */ |
| | | |
| | | struct option opts[] = { |
| | | {"ipaddr", required_argument, NULL, 'i'}, |
| | | {"port", required_argument, NULL, 'p'}, |
| | | {"interval", no_argument, NULL, 'I'}, |
| | | {"debug", no_argument, NULL, 'd'}, |
| | | {"sn", required_argument, NULL, 's'}, |
| | | {"help", no_argument, NULL, 'h'}, |
| | | {NULL, 0, NULL, 0} |
| | | }; |
| | | |
| | | while( (rv=getopt_long(argc, argv, "i:p:dI:s:h", opts, NULL)) != -1 ) |
| | | { |
| | | switch(rv) |
| | | { |
| | | case 'i': |
| | | serverip=optarg; |
| | | break; |
| | | |
| | | case 'p': |
| | | port=atoi(optarg); |
| | | break; |
| | | |
| | | case 'd': |
| | | debug=1; |
| | | logfile="stdout"; |
| | | loglevel=LOG_LEVEL_DEBUG; |
| | | break; |
| | | |
| | | case 'I': |
| | | interval=atoi(optarg); |
| | | break; |
| | | |
| | | case 's': |
| | | sn=atoi(optarg); |
| | | break; |
| | | |
| | | case 'h': |
| | | print_usage(argv[0]); |
| | | return 0; |
| | | } |
| | | |
| | | } |
| | | |
| | | if( !serverip || !port ) |
| | | { |
| | | print_usage(argv[0]); |
| | | return 0; |
| | | } |
| | | |
| | | /* set logger to $logfile with level info */ |
| | | if( logger_init(logfile, loglevel) < 0 ) |
| | | { |
| | | fprintf(stderr, "Initial logger file '%s' failure: %s\n", logfile, strerror(errno)); |
| | | return 1; |
| | | } |
| | | |
| | | if( !debug ) |
| | | { |
| | | log_info("set program running on background now.\n"); |
| | | daemon(1, 1); /* don't change work path, don't close opened file descriptor */ |
| | | } |
| | | |
| | | install_default_signal(); |
| | | |
| | | log_info("program start running.\n"); |
| | | |
| | | if( database_init("client.db") < 0 ) |
| | | { |
| | | return 2; |
| | | } |
| | | |
| | | socket_init(&sock, serverip, port); |
| | | |
| | | while( !g_signal.stop ) |
| | | { |
| | | /* +----------------------------------+ |
| | | * | check and sample temperature | |
| | | * +----------------------------------+*/ |
| | | |
| | | sample_flag = 0; /* clear sample flag */ |
| | | |
| | | if( check_sample_time(&last_time, interval) ) |
| | | { |
| | | log_debug("start DS18B20 sample termperature\n"); |
| | | |
| | | if( (rv=ds18b20_get_temperature(&pack_info.temper)) < 0 ) |
| | | { |
| | | log_error("DS18B20 sample temperature failure, rv=%d\n", rv); |
| | | continue; |
| | | } |
| | | log_info("DS18B20 sample termperature %d.%d oC\n", |
| | | temper_integer(pack_info.temper), temper_fract(pack_info.temper)); |
| | | |
| | | get_devid(pack_info.devid, DEVID_LEN, sn); |
| | | get_time(&pack_info.sample_time); |
| | | |
| | | pack_bytes = pack_proc(&pack_info, pack_buf, sizeof(pack_buf)); |
| | | sample_flag = 1; /* set sample flag */ |
| | | } |
| | | |
| | | /* +---------------------------------+ |
| | | * | check and do socket connect | |
| | | * +---------------------------------+*/ |
| | | |
| | | /* start connect to server if not connected */ |
| | | if( sock.fd < 0 ) |
| | | { |
| | | socket_connect(&sock); |
| | | } |
| | | |
| | | /* check socket connected or not */ |
| | | if( sock_check_connect(sock.fd) < 0 ) |
| | | { |
| | | if( sock.fd > 0 ) |
| | | { |
| | | log_error("socket got disconnected, terminate it and reconnect now.\n"); |
| | | socket_term(&sock); /* close the soket */ |
| | | } |
| | | } |
| | | |
| | | /* +-------------------------------+ |
| | | * | socket disconnect | |
| | | * +-------------------------------+*/ |
| | | if( sock.fd < 0 ) |
| | | { |
| | | if( sample_flag ) |
| | | { |
| | | blobdb_push_packet(pack_buf, pack_bytes); |
| | | } |
| | | |
| | | continue; |
| | | } |
| | | |
| | | /* +-------------------------------+ |
| | | * | socket connected | |
| | | * +-------------------------------+*/ |
| | | |
| | | /* socket send sample packet */ |
| | | if( sample_flag ) |
| | | { |
| | | log_debug("socket send sample packet bytes[%d]: %s\n", pack_bytes, pack_buf); |
| | | if( socket_send(&sock, pack_buf, pack_bytes) < 0 ) |
| | | { |
| | | log_warn("socket send sample packet failure, save it in database now.\n"); |
| | | blobdb_push_packet(pack_buf, pack_bytes); |
| | | socket_term(&sock); /* close the soket */ |
| | | } |
| | | } |
| | | |
| | | /* socket send packet in database */ |
| | | if( !blobdb_pop_packet(pack_buf, sizeof(pack_buf), &pack_bytes) ) |
| | | { |
| | | log_debug("socket send database packet bytes[%d]: %s\n", pack_bytes, pack_buf); |
| | | if( socket_send(&sock, pack_buf, pack_bytes) < 0 ) |
| | | { |
| | | log_error("socket send database packet failure"); |
| | | socket_term(&sock); /* close the soket */ |
| | | } |
| | | else |
| | | { |
| | | log_warn("socket send database packet okay, remove it from database now.\n"); |
| | | blobdb_del_packet(); |
| | | } |
| | | } |
| | | |
| | | msleep(100); |
| | | } |
| | | |
| | | socket_term(&sock); |
| | | database_term(); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int check_sample_time(time_t *last_time, int interval) |
| | | { |
| | | int need = 0; /* no need sample now */ |
| | | time_t now; |
| | | |
| | | time(&now); |
| | | |
| | | if( now >= *last_time+interval ) |
| | | { |
| | | need = 1; /* need sample now */ |
| | | *last_time = now; |
| | | } |
| | | |
| | | return need; |
| | | } |
New file |
| | |
| | | |
| | | LIBS_PATH=`pwd`/../libs/install/ |
| | | |
| | | CFLAGS += -I ${LIBS_PATH}/include/ |
| | | LDFLAGS += -L ${LIBS_PATH}/lib/ -lbooster |
| | | LDFLAGS += -lpthread -lsqlite3 |
| | | |
| | | SRCFILES = $(wildcard *.c) |
| | | BINARIES=$(SRCFILES:%.c=%) |
| | | |
| | | all: clean ${BINARIES} |
| | | |
| | | %: %.c |
| | | $(CC) $(CFLAGS) -o $@ $< ${LDFLAGS} |
| | | |
| | | clean: |
| | | rm -f ${BINARIES} |
| | | |
| | | distclean: clean |
| | | rm -f *.log *.db |
New file |
| | |
| | | #include <stdio.h>
|
| | | #include <stdlib.h>
|
| | | #include <unistd.h>
|
| | | #include <string.h>
|
| | | #include <errno.h>
|
| | | #include <ctype.h>
|
| | | #include <time.h>
|
| | | #include <pthread.h>
|
| | | #include <getopt.h>
|
| | | #include <libgen.h> |
| | | #include <sys/types.h> |
| | | #include <sys/socket.h>
|
| | | #include <arpa/inet.h>
|
| | | #include <netinet/in.h> |
| | | #include <sys/epoll.h>
|
| | | #include <sys/resource.h>
|
| | |
|
| | | #define MAX_EVENTS 512
|
| | | #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
| | |
|
| | | static inline void print_usage(char *progname);
|
| | | int socket_server_init(char *listen_ip, int listen_port);
|
| | | void set_socket_rlimit(void);
|
| | |
|
| | | int main(int argc, char **argv)
|
| | | {
|
| | | int listenfd, connfd;
|
| | | int serv_port = 0;
|
| | | int daemon_run = 0;
|
| | | char *progname = NULL;
|
| | | int opt;
|
| | | int rv;
|
| | | int i, j;
|
| | | int found;
|
| | | char buf[1024];
|
| | |
|
| | | int epollfd;
|
| | | struct epoll_event event;
|
| | | struct epoll_event event_array[MAX_EVENTS];
|
| | | int events;
|
| | | |
| | | struct option long_options[] = |
| | | { |
| | | {"daemon", no_argument, NULL, 'b'},
|
| | | {"port", required_argument, NULL, 'p'},
|
| | | {"help", no_argument, NULL, 'h'},
|
| | | {NULL, 0, NULL, 0}
|
| | | }; |
| | |
|
| | | progname = basename(argv[0]);
|
| | |
|
| | | /* Parser the command line parameters */
|
| | | while ((opt = getopt_long(argc, argv, "bp:h", long_options, NULL)) != -1) |
| | | { |
| | | switch (opt)
|
| | | { |
| | | case 'b':
|
| | | daemon_run=1;
|
| | | break;
|
| | |
|
| | | case 'p':
|
| | | serv_port = atoi(optarg);
|
| | | break;
|
| | |
|
| | | case 'h': /* Get help information */
|
| | | print_usage(progname);
|
| | | return EXIT_SUCCESS;
|
| | |
|
| | | default:
|
| | | break;
|
| | | } |
| | | } |
| | |
|
| | | if( !serv_port ) |
| | | { |
| | | print_usage(progname);
|
| | | return -1; |
| | | }
|
| | |
|
| | | set_socket_rlimit(); /* set max open socket count */
|
| | |
|
| | | if( (listenfd=socket_server_init(NULL, serv_port)) < 0 )
|
| | | {
|
| | | printf("ERROR: %s server listen on port %d failure\n", argv[0],serv_port);
|
| | | return -2;
|
| | | }
|
| | | printf("%s server start to listen on port %d\n", argv[0],serv_port);
|
| | |
|
| | |
|
| | | /* set program running on background */
|
| | | if( daemon_run ) |
| | | {
|
| | | daemon(0, 0);
|
| | | }
|
| | |
|
| | | if( (epollfd=epoll_create(MAX_EVENTS)) < 0 )
|
| | | {
|
| | | printf("epoll_create() failure: %s\n", strerror(errno));
|
| | | return -3;
|
| | | }
|
| | |
|
| | | //event.events = EPOLLIN|EPOLLET;
|
| | | event.events = EPOLLIN;
|
| | | event.data.fd = listenfd;
|
| | |
|
| | | if( epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &event) < 0)
|
| | | {
|
| | | printf("epoll add listen socket failure: %s\n", strerror(errno));
|
| | | return -4;
|
| | | }
|
| | |
|
| | |
|
| | | for ( ; ; ) |
| | | {
|
| | | /* program will blocked here */
|
| | | events = epoll_wait(epollfd, event_array, MAX_EVENTS, -1);
|
| | | if(events < 0)
|
| | | {
|
| | | printf("epoll failure: %s\n", strerror(errno));
|
| | | break;
|
| | | }
|
| | | else if(events == 0)
|
| | | {
|
| | | printf("epoll get timeout\n");
|
| | | continue;
|
| | | }
|
| | |
|
| | | /* rv>0 is the active events count */
|
| | | for(i=0; i<events; i++)
|
| | | {
|
| | | if ( (event_array[i].events&EPOLLERR) || (event_array[i].events&EPOLLHUP) )
|
| | | {
|
| | | printf("epoll_wait get error on fd[%d]: %s\n", event_array[i].data.fd, strerror(errno));
|
| | | epoll_ctl(epollfd, EPOLL_CTL_DEL, event_array[i].data.fd, NULL);
|
| | | close(event_array[i].data.fd);
|
| | | }
|
| | |
|
| | | /* listen socket get event means new client start connect now */
|
| | | if( event_array[i].data.fd == listenfd )
|
| | | { |
| | | if( (connfd=accept(listenfd, (struct sockaddr *)NULL, NULL)) < 0)
|
| | | {
|
| | | printf("accept new client failure: %s\n", strerror(errno));
|
| | | continue;
|
| | | }
|
| | |
|
| | | event.data.fd = connfd;
|
| | | //event.events = EPOLLIN|EPOLLET;
|
| | | event.events = EPOLLIN;
|
| | | if( epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &event) < 0 )
|
| | | {
|
| | | printf("epoll add client socket failure: %s\n", strerror(errno));
|
| | | close(event_array[i].data.fd);
|
| | | continue;
|
| | | }
|
| | | printf("epoll add new client socket[%d] ok.\n", connfd);
|
| | | }
|
| | | else /* already connected client socket get data incoming */
|
| | | {
|
| | | if( (rv=read(event_array[i].data.fd, buf, sizeof(buf))) <= 0)
|
| | | {
|
| | | printf("socket[%d] read failure or get disconncet and will be removed.\n", event_array[i].data.fd);
|
| | | epoll_ctl(epollfd, EPOLL_CTL_DEL, event_array[i].data.fd, NULL);
|
| | | close(event_array[i].data.fd);
|
| | | continue;
|
| | | }
|
| | | else
|
| | | {
|
| | | printf("socket[%d] read get %d bytes data\n", event_array[i].data.fd, rv);
|
| | |
|
| | | /* convert letter from lowercase to uppercase */
|
| | | for(j=0; j<rv; j++)
|
| | | buf[j]=toupper(buf[j]);
|
| | |
|
| | | if( write(event_array[i].data.fd, buf, rv) < 0 )
|
| | | {
|
| | | printf("socket[%d] write failure: %s\n", event_array[i].data.fd, strerror(errno));
|
| | | epoll_ctl(epollfd, EPOLL_CTL_DEL, event_array[i].data.fd, NULL);
|
| | | close(event_array[i].data.fd);
|
| | | } |
| | | } |
| | | } |
| | | } /* for(i=0; i<rv; i++) */
|
| | | } /* while(1) */
|
| | |
|
| | | CleanUp:
|
| | | close(listenfd);
|
| | | return 0;
|
| | | }
|
| | |
|
| | |
|
| | | static inline void print_usage(char *progname)
|
| | | { |
| | | printf("Usage: %s [OPTION]...\n", progname);
|
| | | |
| | | printf(" %s is a socket server program, which used to verify client and echo back string from it\n", progname); |
| | | printf("\nMandatory arguments to long options are mandatory for short options too:\n"); |
| | | |
| | | printf(" -b[daemon ] set program running on background\n");
|
| | | printf(" -p[port ] Socket server port address\n");
|
| | | printf(" -h[help ] Display this help information\n");
|
| | | |
| | |
|
| | | printf("\nExample: %s -b -p 8900\n", progname);
|
| | | return ;
|
| | | }
|
| | |
|
| | |
|
| | | int socket_server_init(char *listen_ip, int listen_port)
|
| | | {
|
| | | struct sockaddr_in servaddr;
|
| | | int rv = 0;
|
| | | int on = 1;
|
| | | int listenfd;
|
| | |
|
| | | if ( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
| | | {
|
| | | printf("Use socket() to create a TCP socket failure: %s\n", strerror(errno));
|
| | | return -1;
|
| | | }
|
| | |
|
| | | /* Set socket port reuseable, fix 'Address already in use' bug when socket server restart */
|
| | | setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
| | |
|
| | | memset(&servaddr, 0, sizeof(servaddr));
|
| | | servaddr.sin_family = AF_INET; |
| | | servaddr.sin_port = htons(listen_port); |
| | |
|
| | | if( !listen_ip ) /* Listen all the local IP address */
|
| | | {
|
| | | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
| | | }
|
| | | else /* listen the specified IP address */
|
| | | {
|
| | | if (inet_pton(AF_INET, listen_ip, &servaddr.sin_addr) <= 0)
|
| | | {
|
| | | printf("inet_pton() set listen IP address failure.\n");
|
| | | rv = -2;
|
| | | goto CleanUp;
|
| | | }
|
| | | }
|
| | |
|
| | |
|
| | | if(bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
|
| | | {
|
| | | printf("Use bind() to bind the TCP socket failure: %s\n", strerror(errno));
|
| | | rv = -3;
|
| | | goto CleanUp;
|
| | | }
|
| | |
|
| | | if(listen(listenfd, 13) < 0)
|
| | | {
|
| | | printf("Use bind() to bind the TCP socket failure: %s\n", strerror(errno));
|
| | | rv = -4;
|
| | | goto CleanUp;
|
| | | }
|
| | |
|
| | | CleanUp:
|
| | | if(rv<0)
|
| | | close(listenfd);
|
| | | else
|
| | | rv = listenfd;
|
| | |
|
| | | return rv;
|
| | | }
|
| | |
|
| | | /* Set open file description count to max */
|
| | | void set_socket_rlimit(void)
|
| | | {
|
| | | struct rlimit limit = {0};
|
| | |
|
| | | getrlimit(RLIMIT_NOFILE, &limit );
|
| | | limit.rlim_cur = limit.rlim_max;
|
| | | setrlimit(RLIMIT_NOFILE, &limit );
|
| | |
|
| | | printf("set socket open fd max count to %d\n", limit.rlim_max);
|
| | | }
|
| | |
|
New file |
| | |
| | | |
| | | all: |
| | | make -C libs |
| | | make -C src && make install -C src |
| | | make -C main |
| | | |
| | | clean: |
| | | make clean -C libs |
| | | make clean -C src |
| | | make clean -C main |
| | | |
| | | distclean: |
| | | make distclean -C libs |
| | | make distclean -C src |
| | | make distclean -C main |
| | | rm -f *.log *.db |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: ds18b20.c |
| | | * Description: This file is get temperature by DS18B20 on RaspberryPi |
| | | * |
| | | * Version: 1.0.0(2020年04月15日) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2020年04月15日 23时14分21秒" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <stdint.h> |
| | | #include <fcntl.h> |
| | | #include <dirent.h> |
| | | #include <string.h> |
| | | #include <time.h> |
| | | #include <errno.h> |
| | | |
| | | #include "logger.h" |
| | | |
| | | /* File Content: |
| | | pi@raspberrypi:~/guowenxue $ cat /sys/bus/w1/devices/28-041731f7c0ff/w1_slave |
| | | 3a 01 4b 46 7f ff 0c 10 a5 : crc=a5 YES |
| | | 3a 01 4b 46 7f ff 0c 10 a5 t=19625 |
| | | */ |
| | | |
| | | int ds18b20_get_temperature(uint16_t *temp) |
| | | { |
| | | char w1_path[50] = "/sys/bus/w1/devices/"; |
| | | char chip[20]; |
| | | char buf[128]; |
| | | DIR *dirp; |
| | | struct dirent *direntp; |
| | | int fd =-1; |
| | | char *ptr; |
| | | uint8_t *byte; |
| | | float value; |
| | | int found = 0; |
| | | |
| | | if( !temp ) |
| | | { |
| | | log_error("ERROR: Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | /*+-------------------------------------------------------------------+ |
| | | *| open dierectory /sys/bus/w1/devices to get chipset Serial Number | |
| | | *+-------------------------------------------------------------------+*/ |
| | | if((dirp = opendir(w1_path)) == NULL) |
| | | { |
| | | log_error("opendir error: %s\n", strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | while((direntp = readdir(dirp)) != NULL) |
| | | { |
| | | if(strstr(direntp->d_name,"28-")) |
| | | { |
| | | /* find and get the chipset SN filename */ |
| | | strcpy(chip,direntp->d_name); |
| | | found = 1; |
| | | break; |
| | | } |
| | | } |
| | | closedir(dirp); |
| | | |
| | | if( !found ) |
| | | { |
| | | log_error("Can not find ds18b20 in %s\n", w1_path); |
| | | return -2; |
| | | } |
| | | |
| | | /* get DS18B20 sample file full path: /sys/bus/w1/devices/28-xxxx/w1_slave */ |
| | | strncat(w1_path, chip, sizeof(w1_path)-strlen(w1_path)); |
| | | strncat(w1_path, "/w1_slave", sizeof(w1_path)-strlen(w1_path)); |
| | | |
| | | /* open file /sys/bus/w1/devices/28-xxxx/w1_slave to get temperature */ |
| | | if( (fd=open(w1_path, O_RDONLY)) < 0 ) |
| | | { |
| | | log_error("open %s error: %s\n", w1_path, strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | if(read(fd, buf, sizeof(buf)) < 0) |
| | | { |
| | | log_error("read %s error: %s\n", w1_path, strerror(errno)); |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | ptr = strstr(buf, "t="); |
| | | if( !ptr ) |
| | | { |
| | | log_error("ERROR: Can not get temperature\n"); |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | ptr+=2; |
| | | |
| | | /* use two bytes to save temperature value */ |
| | | byte = (uint8_t *)temp; |
| | | byte[1] = atoi(ptr)/1000; /* integer part */ |
| | | byte[0] = (atoi(ptr)%1000)/10; /* fractional part, two digits after */ |
| | | |
| | | close(fd); |
| | | return 0; |
| | | } |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: ds18b20.h |
| | | * Description: This head file is get temperature by DS18B20 on RaspberryPi |
| | | * |
| | | * Version: 1.0.0(2020年04月15日) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2020年04月15日 23时37分38秒" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef _DS18B20_H_ |
| | | #define _DS18B20_H_ |
| | | |
| | | #include <stdint.h> |
| | | |
| | | /* description: get temperature by DS18B20 on RaspberryPi |
| | | * return value: 0: Successfully <0: Failure |
| | | * output value: $temp: temperature value saved in two bytes: |
| | | * byte[0]: fractional part, two digits after |
| | | * byte[1]: integer part |
| | | */ |
| | | int ds18b20_get_temperature(uint16_t *temp); |
| | | |
| | | #define temper_integer(x) (((x)>>8) & 0xFF) |
| | | #define temper_fract(x) ( (x) & 0xFF) |
| | | |
| | | #endif /* ----- #ifndef _DS18B20_H_ ----- */ |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com> |
| | | * All rights reserved. |
| | | * |
| | | * Filename: list.h |
| | | * Description: This file is copied from Linux kernel, which provide link list API. |
| | | * |
| | | * Version: 1.0.0(08/09/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "08/09/2012 02:24:34 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef _LINUX_LIST_H |
| | | #define _LINUX_LIST_H |
| | | |
| | | #include <linux/stddef.h> |
| | | |
| | | |
| | | /** |
| | | * container_of - cast a member of a structure out to the containing structure |
| | | * @ptr: the pointer to the member. |
| | | * @type: the type of the container struct this is embedded in. |
| | | * @member: the name of the member within the struct. |
| | | * |
| | | */ |
| | | #undef offsetof |
| | | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) |
| | | #define container_of(ptr, type, member) ({ \ |
| | | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ |
| | | (type *)( (char *)__mptr - offsetof(type,member) );}) |
| | | |
| | | |
| | | /* |
| | | * Architectures might want to move the poison pointer offset |
| | | * into some well-recognized area such as 0xdead000000000000, |
| | | * that is also not mappable by user-space exploits: |
| | | */ |
| | | #ifdef CONFIG_ILLEGAL_POINTER_VALUE |
| | | # define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL) |
| | | #else |
| | | # define POISON_POINTER_DELTA 0 |
| | | #endif |
| | | |
| | | /* |
| | | * These are non-NULL pointers that will result in page faults |
| | | * under normal circumstances, used to verify that nobody uses |
| | | * non-initialized list entries. |
| | | */ |
| | | #define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA) |
| | | #define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA) |
| | | |
| | | #ifndef ARCH_HAS_PREFETCH |
| | | #define ARCH_HAS_PREFETCH |
| | | static inline void prefetch(const void *x) {;} |
| | | #endif |
| | | |
| | | /* |
| | | * Simple doubly linked list implementation. |
| | | * |
| | | * Some of the internal functions ("__xxx") are useful when |
| | | * manipulating whole lists rather than single entries, as |
| | | * sometimes we already know the next/prev entries and we can |
| | | * generate better code by using them directly rather than |
| | | * using the generic single-entry routines. |
| | | */ |
| | | |
| | | struct list_head { |
| | | struct list_head *next, *prev; |
| | | }; |
| | | |
| | | #define LIST_HEAD_INIT(name) { &(name), &(name) } |
| | | |
| | | #define LIST_HEAD(name) \ |
| | | struct list_head name = LIST_HEAD_INIT(name) |
| | | |
| | | static inline void INIT_LIST_HEAD(struct list_head *list) |
| | | { |
| | | list->next = list; |
| | | list->prev = list; |
| | | } |
| | | |
| | | /* |
| | | * Insert a new entry between two known consecutive entries. |
| | | * |
| | | * This is only for internal list manipulation where we know |
| | | * the prev/next entries already! |
| | | */ |
| | | static inline void __list_add(struct list_head *new, |
| | | struct list_head *prev, |
| | | struct list_head *next) |
| | | { |
| | | next->prev = new; |
| | | new->next = next; |
| | | new->prev = prev; |
| | | prev->next = new; |
| | | } |
| | | |
| | | /** |
| | | * list_add - add a new entry |
| | | * @new: new entry to be added |
| | | * @head: list head to add it after |
| | | * |
| | | * Insert a new entry after the specified head. |
| | | * This is good for implementing stacks. |
| | | */ |
| | | static inline void list_add(struct list_head *new, struct list_head *head) |
| | | { |
| | | __list_add(new, head, head->next); |
| | | } |
| | | |
| | | /** |
| | | * list_add_tail - add a new entry |
| | | * @new: new entry to be added |
| | | * @head: list head to add it before |
| | | * |
| | | * Insert a new entry before the specified head. |
| | | * This is useful for implementing queues. |
| | | */ |
| | | static inline void list_add_tail(struct list_head *new, struct list_head *head) |
| | | { |
| | | __list_add(new, head->prev, head); |
| | | } |
| | | |
| | | /* |
| | | * Delete a list entry by making the prev/next entries |
| | | * point to each other. |
| | | * |
| | | * This is only for internal list manipulation where we know |
| | | * the prev/next entries already! |
| | | */ |
| | | static inline void __list_del(struct list_head *prev, struct list_head *next) |
| | | { |
| | | next->prev = prev; |
| | | prev->next = next; |
| | | } |
| | | |
| | | /** |
| | | * list_del - deletes entry from list. |
| | | * @entry: the element to delete from the list. |
| | | * Note: list_empty() on entry does not return true after this, the entry is |
| | | * in an undefined state. |
| | | */ |
| | | static inline void list_del(struct list_head *entry) |
| | | { |
| | | __list_del(entry->prev, entry->next); |
| | | entry->next = LIST_POISON1; |
| | | entry->prev = LIST_POISON2; |
| | | } |
| | | |
| | | /** |
| | | * list_replace - replace old entry by new one |
| | | * @old : the element to be replaced |
| | | * @new : the new element to insert |
| | | * |
| | | * If @old was empty, it will be overwritten. |
| | | */ |
| | | static inline void list_replace(struct list_head *old, |
| | | struct list_head *new) |
| | | { |
| | | new->next = old->next; |
| | | new->next->prev = new; |
| | | new->prev = old->prev; |
| | | new->prev->next = new; |
| | | } |
| | | |
| | | static inline void list_replace_init(struct list_head *old, |
| | | struct list_head *new) |
| | | { |
| | | list_replace(old, new); |
| | | INIT_LIST_HEAD(old); |
| | | } |
| | | |
| | | /** |
| | | * list_del_init - deletes entry from list and reinitialize it. |
| | | * @entry: the element to delete from the list. |
| | | */ |
| | | static inline void list_del_init(struct list_head *entry) |
| | | { |
| | | __list_del(entry->prev, entry->next); |
| | | INIT_LIST_HEAD(entry); |
| | | } |
| | | |
| | | /** |
| | | * list_move - delete from one list and add as another's head |
| | | * @list: the entry to move |
| | | * @head: the head that will precede our entry |
| | | */ |
| | | static inline void list_move(struct list_head *list, struct list_head *head) |
| | | { |
| | | __list_del(list->prev, list->next); |
| | | list_add(list, head); |
| | | } |
| | | |
| | | /** |
| | | * list_move_tail - delete from one list and add as another's tail |
| | | * @list: the entry to move |
| | | * @head: the head that will follow our entry |
| | | */ |
| | | static inline void list_move_tail(struct list_head *list, |
| | | struct list_head *head) |
| | | { |
| | | __list_del(list->prev, list->next); |
| | | list_add_tail(list, head); |
| | | } |
| | | |
| | | /** |
| | | * list_is_last - tests whether @list is the last entry in list @head |
| | | * @list: the entry to test |
| | | * @head: the head of the list |
| | | */ |
| | | static inline int list_is_last(const struct list_head *list, |
| | | const struct list_head *head) |
| | | { |
| | | return list->next == head; |
| | | } |
| | | |
| | | /** |
| | | * list_empty - tests whether a list is empty |
| | | * @head: the list to test. |
| | | */ |
| | | static inline int list_empty(const struct list_head *head) |
| | | { |
| | | return head->next == head; |
| | | } |
| | | |
| | | /** |
| | | * list_empty_careful - tests whether a list is empty and not being modified |
| | | * @head: the list to test |
| | | * |
| | | * Description: |
| | | * tests whether a list is empty _and_ checks that no other CPU might be |
| | | * in the process of modifying either member (next or prev) |
| | | * |
| | | * NOTE: using list_empty_careful() without synchronization |
| | | * can only be safe if the only activity that can happen |
| | | * to the list entry is list_del_init(). Eg. it cannot be used |
| | | * if another CPU could re-list_add() it. |
| | | */ |
| | | static inline int list_empty_careful(const struct list_head *head) |
| | | { |
| | | struct list_head *next = head->next; |
| | | return (next == head) && (next == head->prev); |
| | | } |
| | | |
| | | /** |
| | | * list_is_singular - tests whether a list has just one entry. |
| | | * @head: the list to test. |
| | | */ |
| | | static inline int list_is_singular(const struct list_head *head) |
| | | { |
| | | return !list_empty(head) && (head->next == head->prev); |
| | | } |
| | | |
| | | static inline void __list_cut_position(struct list_head *list, |
| | | struct list_head *head, struct list_head *entry) |
| | | { |
| | | struct list_head *new_first = entry->next; |
| | | list->next = head->next; |
| | | list->next->prev = list; |
| | | list->prev = entry; |
| | | entry->next = list; |
| | | head->next = new_first; |
| | | new_first->prev = head; |
| | | } |
| | | |
| | | /** |
| | | * list_cut_position - cut a list into two |
| | | * @list: a new list to add all removed entries |
| | | * @head: a list with entries |
| | | * @entry: an entry within head, could be the head itself |
| | | * and if so we won't cut the list |
| | | * |
| | | * This helper moves the initial part of @head, up to and |
| | | * including @entry, from @head to @list. You should |
| | | * pass on @entry an element you know is on @head. @list |
| | | * should be an empty list or a list you do not care about |
| | | * losing its data. |
| | | * |
| | | */ |
| | | static inline void list_cut_position(struct list_head *list, |
| | | struct list_head *head, struct list_head *entry) |
| | | { |
| | | if (list_empty(head)) |
| | | return; |
| | | if (list_is_singular(head) && |
| | | (head->next != entry && head != entry)) |
| | | return; |
| | | if (entry == head) |
| | | INIT_LIST_HEAD(list); |
| | | else |
| | | __list_cut_position(list, head, entry); |
| | | } |
| | | |
| | | static inline void __list_splice(const struct list_head *list, |
| | | struct list_head *prev, |
| | | struct list_head *next) |
| | | { |
| | | struct list_head *first = list->next; |
| | | struct list_head *last = list->prev; |
| | | |
| | | first->prev = prev; |
| | | prev->next = first; |
| | | |
| | | last->next = next; |
| | | next->prev = last; |
| | | } |
| | | |
| | | /** |
| | | * list_splice - join two lists, this is designed for stacks |
| | | * @list: the new list to add. |
| | | * @head: the place to add it in the first list. |
| | | */ |
| | | static inline void list_splice(const struct list_head *list, |
| | | struct list_head *head) |
| | | { |
| | | if (!list_empty(list)) |
| | | __list_splice(list, head, head->next); |
| | | } |
| | | |
| | | /** |
| | | * list_splice_tail - join two lists, each list being a queue |
| | | * @list: the new list to add. |
| | | * @head: the place to add it in the first list. |
| | | */ |
| | | static inline void list_splice_tail(struct list_head *list, |
| | | struct list_head *head) |
| | | { |
| | | if (!list_empty(list)) |
| | | __list_splice(list, head->prev, head); |
| | | } |
| | | |
| | | /** |
| | | * list_splice_init - join two lists and reinitialise the emptied list. |
| | | * @list: the new list to add. |
| | | * @head: the place to add it in the first list. |
| | | * |
| | | * The list at @list is reinitialised |
| | | */ |
| | | static inline void list_splice_init(struct list_head *list, |
| | | struct list_head *head) |
| | | { |
| | | if (!list_empty(list)) { |
| | | __list_splice(list, head, head->next); |
| | | INIT_LIST_HEAD(list); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * list_splice_tail_init - join two lists and reinitialise the emptied list |
| | | * @list: the new list to add. |
| | | * @head: the place to add it in the first list. |
| | | * |
| | | * Each of the lists is a queue. |
| | | * The list at @list is reinitialised |
| | | */ |
| | | static inline void list_splice_tail_init(struct list_head *list, |
| | | struct list_head *head) |
| | | { |
| | | if (!list_empty(list)) { |
| | | __list_splice(list, head->prev, head); |
| | | INIT_LIST_HEAD(list); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * list_entry - get the struct for this entry |
| | | * @ptr: the &struct list_head pointer. |
| | | * @type: the type of the struct this is embedded in. |
| | | * @member: the name of the list_struct within the struct. |
| | | */ |
| | | #define list_entry(ptr, type, member) \ |
| | | container_of(ptr, type, member) |
| | | |
| | | /** |
| | | * list_first_entry - get the first element from a list |
| | | * @ptr: the list head to take the element from. |
| | | * @type: the type of the struct this is embedded in. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Note, that list is expected to be not empty. |
| | | */ |
| | | #define list_first_entry(ptr, type, member) \ |
| | | list_entry((ptr)->next, type, member) |
| | | |
| | | /** |
| | | * list_for_each - iterate over a list |
| | | * @pos: the &struct list_head to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | */ |
| | | #define list_for_each(pos, head) \ |
| | | for (pos = (head)->next; prefetch(pos->next), pos != (head); \ |
| | | pos = pos->next) |
| | | |
| | | /** |
| | | * __list_for_each - iterate over a list |
| | | * @pos: the &struct list_head to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * |
| | | * This variant differs from list_for_each() in that it's the |
| | | * simplest possible list iteration code, no prefetching is done. |
| | | * Use this for code that knows the list to be very short (empty |
| | | * or 1 entry) most of the time. |
| | | */ |
| | | #define __list_for_each(pos, head) \ |
| | | for (pos = (head)->next; pos != (head); pos = pos->next) |
| | | |
| | | /** |
| | | * list_for_each_prev - iterate over a list backwards |
| | | * @pos: the &struct list_head to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | */ |
| | | #define list_for_each_prev(pos, head) \ |
| | | for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ |
| | | pos = pos->prev) |
| | | |
| | | /** |
| | | * list_for_each_safe - iterate over a list safe against removal of list entry |
| | | * @pos: the &struct list_head to use as a loop cursor. |
| | | * @n: another &struct list_head to use as temporary storage |
| | | * @head: the head for your list. |
| | | */ |
| | | #define list_for_each_safe(pos, n, head) \ |
| | | for (pos = (head)->next, n = pos->next; pos != (head); \ |
| | | pos = n, n = pos->next) |
| | | |
| | | /** |
| | | * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry |
| | | * @pos: the &struct list_head to use as a loop cursor. |
| | | * @n: another &struct list_head to use as temporary storage |
| | | * @head: the head for your list. |
| | | */ |
| | | #define list_for_each_prev_safe(pos, n, head) \ |
| | | for (pos = (head)->prev, n = pos->prev; \ |
| | | prefetch(pos->prev), pos != (head); \ |
| | | pos = n, n = pos->prev) |
| | | |
| | | /** |
| | | * list_for_each_entry - iterate over list of given type |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | */ |
| | | #define list_for_each_entry(pos, head, member) \ |
| | | for (pos = list_entry((head)->next, typeof(*pos), member); \ |
| | | prefetch(pos->member.next), &pos->member != (head); \ |
| | | pos = list_entry(pos->member.next, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_reverse - iterate backwards over list of given type. |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | */ |
| | | #define list_for_each_entry_reverse(pos, head, member) \ |
| | | for (pos = list_entry((head)->prev, typeof(*pos), member); \ |
| | | prefetch(pos->member.prev), &pos->member != (head); \ |
| | | pos = list_entry(pos->member.prev, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() |
| | | * @pos: the type * to use as a start point |
| | | * @head: the head of the list |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). |
| | | */ |
| | | #define list_prepare_entry(pos, head, member) \ |
| | | ((pos) ? : list_entry(head, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_continue - continue iteration over list of given type |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Continue to iterate over list of given type, continuing after |
| | | * the current position. |
| | | */ |
| | | #define list_for_each_entry_continue(pos, head, member) \ |
| | | for (pos = list_entry(pos->member.next, typeof(*pos), member); \ |
| | | prefetch(pos->member.next), &pos->member != (head); \ |
| | | pos = list_entry(pos->member.next, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_continue_reverse - iterate backwards from the given point |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Start to iterate over list of given type backwards, continuing after |
| | | * the current position. |
| | | */ |
| | | #define list_for_each_entry_continue_reverse(pos, head, member) \ |
| | | for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ |
| | | prefetch(pos->member.prev), &pos->member != (head); \ |
| | | pos = list_entry(pos->member.prev, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_from - iterate over list of given type from the current point |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Iterate over list of given type, continuing from current position. |
| | | */ |
| | | #define list_for_each_entry_from(pos, head, member) \ |
| | | for (; prefetch(pos->member.next), &pos->member != (head); \ |
| | | pos = list_entry(pos->member.next, typeof(*pos), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @n: another type * to use as temporary storage |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | */ |
| | | #define list_for_each_entry_safe(pos, n, head, member) \ |
| | | for (pos = list_entry((head)->next, typeof(*pos), member), \ |
| | | n = list_entry(pos->member.next, typeof(*pos), member); \ |
| | | &pos->member != (head); \ |
| | | pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_safe_continue |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @n: another type * to use as temporary storage |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Iterate over list of given type, continuing after current point, |
| | | * safe against removal of list entry. |
| | | */ |
| | | #define list_for_each_entry_safe_continue(pos, n, head, member) \ |
| | | for (pos = list_entry(pos->member.next, typeof(*pos), member), \ |
| | | n = list_entry(pos->member.next, typeof(*pos), member); \ |
| | | &pos->member != (head); \ |
| | | pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_safe_from |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @n: another type * to use as temporary storage |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Iterate over list of given type from current point, safe against |
| | | * removal of list entry. |
| | | */ |
| | | #define list_for_each_entry_safe_from(pos, n, head, member) \ |
| | | for (n = list_entry(pos->member.next, typeof(*pos), member); \ |
| | | &pos->member != (head); \ |
| | | pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
| | | |
| | | /** |
| | | * list_for_each_entry_safe_reverse |
| | | * @pos: the type * to use as a loop cursor. |
| | | * @n: another type * to use as temporary storage |
| | | * @head: the head for your list. |
| | | * @member: the name of the list_struct within the struct. |
| | | * |
| | | * Iterate backwards over list of given type, safe against removal |
| | | * of list entry. |
| | | */ |
| | | #define list_for_each_entry_safe_reverse(pos, n, head, member) \ |
| | | for (pos = list_entry((head)->prev, typeof(*pos), member), \ |
| | | n = list_entry(pos->member.prev, typeof(*pos), member); \ |
| | | &pos->member != (head); \ |
| | | pos = n, n = list_entry(n->member.prev, typeof(*n), member)) |
| | | |
| | | /* |
| | | * Double linked lists with a single pointer list head. |
| | | * Mostly useful for hash tables where the two pointer list head is |
| | | * too wasteful. |
| | | * You lose the ability to access the tail in O(1). |
| | | */ |
| | | |
| | | struct hlist_head { |
| | | struct hlist_node *first; |
| | | }; |
| | | |
| | | struct hlist_node { |
| | | struct hlist_node *next, **pprev; |
| | | }; |
| | | |
| | | #define HLIST_HEAD_INIT { .first = NULL } |
| | | #define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } |
| | | #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) |
| | | static inline void INIT_HLIST_NODE(struct hlist_node *h) |
| | | { |
| | | h->next = NULL; |
| | | h->pprev = NULL; |
| | | } |
| | | |
| | | static inline int hlist_unhashed(const struct hlist_node *h) |
| | | { |
| | | return !h->pprev; |
| | | } |
| | | |
| | | static inline int hlist_empty(const struct hlist_head *h) |
| | | { |
| | | return !h->first; |
| | | } |
| | | |
| | | static inline void __hlist_del(struct hlist_node *n) |
| | | { |
| | | struct hlist_node *next = n->next; |
| | | struct hlist_node **pprev = n->pprev; |
| | | *pprev = next; |
| | | if (next) |
| | | next->pprev = pprev; |
| | | } |
| | | |
| | | static inline void hlist_del(struct hlist_node *n) |
| | | { |
| | | __hlist_del(n); |
| | | n->next = LIST_POISON1; |
| | | n->pprev = LIST_POISON2; |
| | | } |
| | | |
| | | static inline void hlist_del_init(struct hlist_node *n) |
| | | { |
| | | if (!hlist_unhashed(n)) { |
| | | __hlist_del(n); |
| | | INIT_HLIST_NODE(n); |
| | | } |
| | | } |
| | | |
| | | static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) |
| | | { |
| | | struct hlist_node *first = h->first; |
| | | n->next = first; |
| | | if (first) |
| | | first->pprev = &n->next; |
| | | h->first = n; |
| | | n->pprev = &h->first; |
| | | } |
| | | |
| | | /* next must be != NULL */ |
| | | static inline void hlist_add_before(struct hlist_node *n, |
| | | struct hlist_node *next) |
| | | { |
| | | n->pprev = next->pprev; |
| | | n->next = next; |
| | | next->pprev = &n->next; |
| | | *(n->pprev) = n; |
| | | } |
| | | |
| | | static inline void hlist_add_after(struct hlist_node *n, |
| | | struct hlist_node *next) |
| | | { |
| | | next->next = n->next; |
| | | n->next = next; |
| | | next->pprev = &n->next; |
| | | |
| | | if(next->next) |
| | | next->next->pprev = &next->next; |
| | | } |
| | | |
| | | #define hlist_entry(ptr, type, member) container_of(ptr,type,member) |
| | | |
| | | #define hlist_for_each(pos, head) \ |
| | | for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ |
| | | pos = pos->next) |
| | | |
| | | #define hlist_for_each_safe(pos, n, head) \ |
| | | for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ |
| | | pos = n) |
| | | |
| | | /** |
| | | * hlist_for_each_entry - iterate over list of given type |
| | | * @tpos: the type * to use as a loop cursor. |
| | | * @pos: the &struct hlist_node to use as a loop cursor. |
| | | * @head: the head for your list. |
| | | * @member: the name of the hlist_node within the struct. |
| | | */ |
| | | #define hlist_for_each_entry(tpos, pos, head, member) \ |
| | | for (pos = (head)->first; \ |
| | | pos && ({ prefetch(pos->next); 1;}) && \ |
| | | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
| | | pos = pos->next) |
| | | |
| | | /** |
| | | * hlist_for_each_entry_continue - iterate over a hlist continuing after current point |
| | | * @tpos: the type * to use as a loop cursor. |
| | | * @pos: the &struct hlist_node to use as a loop cursor. |
| | | * @member: the name of the hlist_node within the struct. |
| | | */ |
| | | #define hlist_for_each_entry_continue(tpos, pos, member) \ |
| | | for (pos = (pos)->next; \ |
| | | pos && ({ prefetch(pos->next); 1;}) && \ |
| | | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
| | | pos = pos->next) |
| | | |
| | | /** |
| | | * hlist_for_each_entry_from - iterate over a hlist continuing from current point |
| | | * @tpos: the type * to use as a loop cursor. |
| | | * @pos: the &struct hlist_node to use as a loop cursor. |
| | | * @member: the name of the hlist_node within the struct. |
| | | */ |
| | | #define hlist_for_each_entry_from(tpos, pos, member) \ |
| | | for (; pos && ({ prefetch(pos->next); 1;}) && \ |
| | | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
| | | pos = pos->next) |
| | | |
| | | /** |
| | | * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry |
| | | * @tpos: the type * to use as a loop cursor. |
| | | * @pos: the &struct hlist_node to use as a loop cursor. |
| | | * @n: another &struct hlist_node to use as temporary storage |
| | | * @head: the head for your list. |
| | | * @member: the name of the hlist_node within the struct. |
| | | */ |
| | | #define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ |
| | | for (pos = (head)->first; \ |
| | | pos && ({ n = pos->next; 1; }) && \ |
| | | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
| | | pos = n) |
| | | |
| | | |
| | | #endif |
| | | |
| | | |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2022 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: logger.c |
| | | * Description: This file |
| | | * |
| | | * Version: 1.0.0(15/04/22) |
| | | * Author: LingYun <lingyun@email.com> |
| | | * ChangeLog: 1, Release initial version on "15/04/22 10:38:49" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <errno.h> |
| | | #include <time.h> |
| | | #include <stdarg.h> |
| | | #include <string.h> |
| | | #include "logger.h" |
| | | |
| | | /* |
| | | * Program name variable is provided by the libc |
| | | */ |
| | | extern const char* __progname; |
| | | #define PROGRAM_NAME __progname |
| | | |
| | | /* |
| | | * Logger internal sctructure |
| | | */ |
| | | typedef struct logger_s { |
| | | FILE *fp; |
| | | int loglevel; |
| | | int use_stdout; |
| | | } logger_t; |
| | | |
| | | static struct logger_s g_logger; |
| | | |
| | | static const char* LOG_LEVELS[] = { |
| | | LOG_STRING_ERROR, |
| | | LOG_STRING_WARN, |
| | | LOG_STRING_INFO, |
| | | LOG_STRING_DEBUG |
| | | }; |
| | | |
| | | /* |
| | | * initial logger system |
| | | */ |
| | | int logger_init(char *filename, int loglevel) |
| | | { |
| | | logger_term(); |
| | | |
| | | g_logger.loglevel = loglevel>LOG_LEVEL_MAX ? LOG_LEVEL_MAX : loglevel; |
| | | |
| | | /* $filename is NULL or match "stdout" will use standard output */ |
| | | if( !filename || !strcasecmp(filename, "stdout")) |
| | | { |
| | | g_logger.use_stdout = 1; |
| | | g_logger.fp = stderr; |
| | | } |
| | | else |
| | | { |
| | | g_logger.use_stdout = 0; |
| | | g_logger.fp = fopen(filename, "a"); |
| | | if( !g_logger.fp ) |
| | | { |
| | | fprintf(stderr, "Failed to open file '%s': %s", filename, strerror(errno)); |
| | | return -1; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* |
| | | * terminate logger system |
| | | */ |
| | | void logger_term(void) |
| | | { |
| | | if( !g_logger.fp ) |
| | | { |
| | | return ; |
| | | } |
| | | |
| | | if( !g_logger.use_stdout ) |
| | | { |
| | | fclose(g_logger.fp); |
| | | } |
| | | |
| | | g_logger.use_stdout = 0; |
| | | g_logger.fp = NULL; |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | /* |
| | | * Logging functions |
| | | */ |
| | | void log_generic(const int level, const char* format, va_list args) |
| | | { |
| | | char message[256]; |
| | | struct tm* current_tm; |
| | | time_t time_now; |
| | | |
| | | vsprintf(message, format, args); |
| | | |
| | | time(&time_now); |
| | | current_tm = localtime(&time_now); |
| | | |
| | | int res = fprintf(g_logger.fp, |
| | | "<%s> %02i:%02i:%02i [%s] %s" |
| | | , PROGRAM_NAME |
| | | , current_tm->tm_hour |
| | | , current_tm->tm_min |
| | | , current_tm->tm_sec |
| | | , LOG_LEVELS[level] |
| | | , message ); |
| | | |
| | | fflush(g_logger.fp); |
| | | } |
| | | |
| | | void log_error(char *format, ...) |
| | | { |
| | | va_list args; |
| | | va_start(args, format); |
| | | log_generic(LOG_LEVEL_ERROR, format, args); |
| | | va_end(args); |
| | | } |
| | | |
| | | void log_warn(char *format, ...) |
| | | { |
| | | if (g_logger.loglevel < LOG_LEVEL_WARN) { |
| | | return; |
| | | } |
| | | |
| | | va_list args; |
| | | va_start(args, format); |
| | | log_generic(LOG_LEVEL_WARN, format, args); |
| | | va_end(args); |
| | | } |
| | | |
| | | void log_info(char *format, ...) |
| | | { |
| | | if (g_logger.loglevel < LOG_LEVEL_INFO) { |
| | | return; |
| | | } |
| | | |
| | | va_list args; |
| | | va_start(args, format); |
| | | log_generic(LOG_LEVEL_INFO, format, args); |
| | | va_end(args); |
| | | } |
| | | |
| | | void log_debug(char *format, ...) |
| | | { |
| | | if (g_logger.loglevel < LOG_LEVEL_DEBUG) { |
| | | return; |
| | | } |
| | | |
| | | va_list args; |
| | | va_start(args, format); |
| | | log_generic(LOG_LEVEL_DEBUG, format, args); |
| | | va_end(args); |
| | | } |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2022 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: logger.h |
| | | * Description: This head file |
| | | * |
| | | * Version: 1.0.0(15/04/22) |
| | | * Author: LingYun <lingyun@email.com> |
| | | * ChangeLog: 1, Release initial version on "15/04/22 10:38:02" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef _LOGGER_H_ |
| | | #define _LOGGER_H_ |
| | | |
| | | /* |
| | | * logger level |
| | | */ |
| | | enum |
| | | { |
| | | LOG_LEVEL_ERROR, |
| | | LOG_LEVEL_WARN, |
| | | LOG_LEVEL_INFO, |
| | | LOG_LEVEL_DEBUG, |
| | | LOG_LEVEL_MAX, |
| | | }; |
| | | |
| | | /* |
| | | * logger prefix string for different logging levels |
| | | */ |
| | | #define LOG_STRING_ERROR "ERROR" |
| | | #define LOG_STRING_WARN "WARN " |
| | | #define LOG_STRING_INFO "INFO " |
| | | #define LOG_STRING_DEBUG "DEBUG" |
| | | |
| | | |
| | | /* |
| | | * logger initial and terminate functions |
| | | */ |
| | | int logger_init(char *filename, int loglevel); |
| | | void logger_term(void); |
| | | |
| | | /* |
| | | * logging methods by levels |
| | | */ |
| | | void log_error(char* format, ...); |
| | | void log_warn(char* format, ...); |
| | | void log_info(char* format, ...); |
| | | void log_debug(char* format, ...); |
| | | |
| | | #endif /* ----- #ifndef _LOGGER_H_ ----- */ |
New file |
| | |
| | | |
| | | LIBNAME = booster |
| | | |
| | | PREFIX ?= `pwd`/../libs/install |
| | | CFLAGS += -I ${PREFIX}/include |
| | | |
| | | INCFILES = $(wildcard *.h) |
| | | SRCFILES = $(wildcard *.c) |
| | | OBJFILES = $(patsubst %.c,%.o,$(SRCFILES)) |
| | | |
| | | all: $(OBJFILES) |
| | | @${AR} -rcs lib${LIBNAME}.a ${OBJFILES} |
| | | |
| | | %.o : %.c |
| | | @$(CC) $(CFLAGS) -c $< |
| | | |
| | | clean: |
| | | @rm -f *.o |
| | | rm -rf lib${LIBNAME}.* |
| | | |
| | | distclean: clean |
| | | |
| | | install: all |
| | | install lib${LIBNAME}.* ${PREFIX}/lib |
| | | install ${INCFILES} ${PREFIX}/include |
| | | |
| | | uninstall: |
| | | rm -f ${PREFIX}/lib/lib${LIBNAME}.* |
| | | rm -f ${PREFIX}/include/${INCFILES} |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2022 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: packet.c |
| | | * Description: This file is packet API functions |
| | | * |
| | | * Version: 1.0.0(18/04/22) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "18/04/22 16:30:25" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | #include <time.h> |
| | | #include "packet.h" |
| | | #include "logger.h" |
| | | #include "ds18b20.h" |
| | | |
| | | int get_devid(char *devid, int size, int sn) |
| | | { |
| | | if( !devid || size<DEVID_LEN ) |
| | | { |
| | | log_error("Invalid input arugments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | memset(devid, 0, size); |
| | | snprintf(devid, size, "rpi#%04d", sn); |
| | | return 0; |
| | | } |
| | | |
| | | int get_time(struct tm *ptm) |
| | | { |
| | | if( !ptm ) |
| | | { |
| | | log_error("Invalid input arugments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | |
| | | time_t now = time(NULL); |
| | | localtime_r(&now, ptm); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int packet_segmented_pack(pack_info_t *pack_info, char *pack_buf, int size) |
| | | { |
| | | char strtime[TIME_LEN] = {'\0'}; |
| | | struct tm *ptm; |
| | | |
| | | if( !pack_info || !pack_buf || size<=0 ) |
| | | { |
| | | log_error("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | ptm = &pack_info->sample_time; |
| | | snprintf(strtime, sizeof(strtime), "%04d-%02d-%2d %02d:%02d:%02d", |
| | | ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday, |
| | | ptm->tm_hour, ptm->tm_min, ptm->tm_sec); |
| | | |
| | | |
| | | memset(pack_buf, 0, size); |
| | | snprintf(pack_buf, size, "%s|%s|%d.%d", pack_info->devid, strtime, |
| | | temper_integer(pack_info->temper), temper_fract(pack_info->temper)); |
| | | |
| | | return strlen(pack_buf); |
| | | } |
| | | |
| | | int packet_json_pack(pack_info_t *pack_info, char *pack_buf, int size) |
| | | { |
| | | char strtime[TIME_LEN] = {'\0'}; |
| | | struct tm *ptm; |
| | | |
| | | if( !pack_info || !pack_buf || size<=0 ) |
| | | { |
| | | log_error("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | ptm = &pack_info->sample_time; |
| | | snprintf(strtime, sizeof(strtime), "%04d-%02d-%2d %02d:%02d:%02d", |
| | | ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday, |
| | | ptm->tm_hour, ptm->tm_min, ptm->tm_sec); |
| | | |
| | | memset(pack_buf, 0, size); |
| | | snprintf(pack_buf, size, "{\"devid\":\"%s\", \"time\":\"%s\",\"temperature\":\"%d.%d\"}", |
| | | pack_info->devid, strtime, temper_integer(pack_info->temper), temper_fract(pack_info->temper)); |
| | | |
| | | return strlen(pack_buf); |
| | | } |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2022 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: packet.h |
| | | * Description: This head file is packet API functions. |
| | | * |
| | | * Version: 1.0.0(18/04/22) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "18/04/22 16:24:40" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | |
| | | #ifndef _PACKET_H_ |
| | | #define _PACKET_H_ |
| | | |
| | | #include <stdint.h> |
| | | #include <time.h> |
| | | |
| | | #define DEVID_LEN 16 |
| | | #define TIME_LEN 32 |
| | | |
| | | typedef struct pack_info_s |
| | | { |
| | | char devid[DEVID_LEN]; /* device ID */ |
| | | struct tm sample_time; /* sample time */ |
| | | uint16_t temper; /* sample temperature */ |
| | | } pack_info_t; |
| | | |
| | | /* packet function pointer type */ |
| | | typedef int (* pack_proc_t)(pack_info_t *pack_info, char *pack_buf, int size); |
| | | |
| | | /* description: get device ID |
| | | * input args: |
| | | * $devid : device ID string |
| | | * $size : device ID output buffer size |
| | | * $sn : serial number |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | extern int get_devid(char *devid, int size, int sn); |
| | | |
| | | /* description: get current system in struct tm |
| | | * input args: |
| | | * $sample_time: sample time in struct tm |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | extern int get_time(struct tm *sample_time); |
| | | |
| | | /* description: package a string packet in format "devid|time|temper" |
| | | * input args: |
| | | * $pack_info: packet data contains devid, time and temperature |
| | | * $pack_buf : packet output buffer |
| | | * $size : packet output buffer size |
| | | * return value: <0: failure >0: packet bytes |
| | | */ |
| | | extern int packet_segmented_pack(pack_info_t *pack_info, char *pack_buf, int size); |
| | | |
| | | |
| | | /* description: package a json string packet: {"devid":"xxx", "time":"xxx", "temperature":"xxx"} |
| | | * input args: |
| | | * $pack_info: packet data contains devid, time and temperature |
| | | * $pack_buf : packet output buffer |
| | | * $size : packet output buffer size |
| | | * return value: <0: failure >0: packet bytes |
| | | */ |
| | | extern int packet_json_pack(pack_info_t *pack_info, char *pack_buf, int size); |
| | | |
| | | |
| | | #endif /* ----- #ifndef _PACKET_H_ ----- */ |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2022 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: socket.c |
| | | * Description: This file is for socket API functions |
| | | * |
| | | * Version: 1.0.0(18/04/22) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "18/04/22 17:09:59" |
| | | * |
| | | ********************************************************************************/ |
| | | #include <stdio.h> |
| | | #include <unistd.h> |
| | | #include <string.h> |
| | | #include <netdb.h> |
| | | #include <fcntl.h> |
| | | #include <unistd.h> |
| | | #include <sys/un.h> |
| | | #include <poll.h> |
| | | #include <errno.h> |
| | | #include <sys/types.h> |
| | | #include <sys/socket.h> |
| | | #include <linux/sockios.h> |
| | | #include <sys/ioctl.h> |
| | | #include <sys/socket.h> |
| | | #include <netinet/in.h> |
| | | #include <netinet/tcp.h> |
| | | #include <arpa/inet.h> |
| | | #include <sys/resource.h> |
| | | |
| | | #include "socket.h" |
| | | #include "logger.h" |
| | | |
| | | /* description: initial socket context |
| | | * input args: |
| | | * $sock: socket context pointer |
| | | * $host: connect server hostname for client mode, unused for server mode |
| | | * $port: connect server port for client mode or listen port for server mode |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | int socket_init(socket_ctx_t *sock, char *host, int port) |
| | | { |
| | | if( !sock || port<=0 ) |
| | | return -1; |
| | | |
| | | memset( sock, 0, sizeof(*sock) ); |
| | | sock->fd = -1; |
| | | sock->port = port; |
| | | if( host ) /* server no need it */ |
| | | strncpy(sock->host, host, HOSTNAME_LEN); |
| | | } |
| | | |
| | | /* description: close socket |
| | | * input args: |
| | | * $sock: socket context pointer |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | int socket_term(socket_ctx_t *sock) |
| | | { |
| | | if( !sock ) |
| | | return -1; |
| | | |
| | | if( sock->fd > 0) |
| | | { |
| | | close(sock->fd); |
| | | sock->fd = -1; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* description: socket server start listen |
| | | * input args: |
| | | * $sock: socket context pointer |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | int socket_listen(socket_ctx_t *sock) |
| | | { |
| | | int rv = 0; |
| | | struct sockaddr_in addr; |
| | | int backlog = 13; |
| | | |
| | | if( !sock ) |
| | | return -1; |
| | | |
| | | set_socket_rlimit(); /* set max open socket count */ |
| | | } |
| | | |
| | | /* description: socket connect to server in block mode |
| | | * input args: |
| | | * $sock: socket context pointer |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | int socket_connect(socket_ctx_t *sock) |
| | | { |
| | | int rv = 0; |
| | | int sockfd = 0; |
| | | struct sockaddr_in servaddr; |
| | | char service[20]; |
| | | struct addrinfo hints, *rp; |
| | | struct addrinfo *res = NULL; |
| | | struct in_addr inaddr; |
| | | struct sockaddr_in addr; |
| | | int len = sizeof(addr); |
| | | |
| | | if( !sock ) |
| | | return -1; |
| | | |
| | | socket_term(sock); |
| | | |
| | | /*+--------------------------------------------------+ |
| | | *| use getaddrinfo() to do domain name translation | |
| | | *+--------------------------------------------------+*/ |
| | | |
| | | memset(&hints, 0, sizeof(struct addrinfo)); |
| | | hints.ai_family = AF_INET; /* Only support IPv4 */ |
| | | hints.ai_socktype = SOCK_STREAM; |
| | | hints.ai_protocol = IPPROTO_TCP; /* TCP protocol */ |
| | | |
| | | /* If $host is a valid IP address, then don't use name resolution */ |
| | | if( inet_aton(sock->host, &inaddr) ) |
| | | { |
| | | //log_info("%s is a valid IP address, don't use domain name resolution.\n", sock->host); |
| | | hints.ai_flags |= AI_NUMERICHOST; |
| | | } |
| | | |
| | | /* Obtain address(es) matching host/port */ |
| | | snprintf(service, sizeof(service), "%d", sock->port); |
| | | if( (rv=getaddrinfo(sock->host, service, &hints, &res)) ) |
| | | { |
| | | log_error("getaddrinfo() parser [%s:%s] failed: %s\n", sock->host, service, gai_strerror(rv)); |
| | | return -3; |
| | | } |
| | | |
| | | /* getaddrinfo() returns a list of address structures. Try each |
| | | address until we successfully connect or bind */ |
| | | for (rp=res; rp!=NULL; rp=rp->ai_next) |
| | | { |
| | | #if 0 |
| | | char ipaddr[INET_ADDRSTRLEN]; |
| | | struct sockaddr_in *sp = (struct sockaddr_in *) rp->ai_addr; |
| | | |
| | | /* print domain name translation result */ |
| | | memset( ipaddr, 0, sizeof(ipaddr) ); |
| | | if( inet_ntop(AF_INET, &sp->sin_addr, ipaddr, sizeof(ipaddr)) ) |
| | | { |
| | | log_info("domain name resolution [%s->%s]\n", sock->host, ipaddr); |
| | | } |
| | | #endif |
| | | |
| | | /* Create the socket */ |
| | | sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); |
| | | if( sockfd < 0) |
| | | { |
| | | log_error("socket() create failed: %s\n", strerror(errno)); |
| | | rv = -3; |
| | | continue; |
| | | } |
| | | |
| | | /* connect to server */ |
| | | rv = connect(sockfd, rp->ai_addr, len); |
| | | if( 0 == rv ) |
| | | { |
| | | sock->fd = sockfd; |
| | | log_info("Connect to server[%s:%d] on fd[%d] successfully!\n", sock->host, sock->port, sockfd); |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | /* socket connect get error, try another IP address */ |
| | | close(sockfd); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | freeaddrinfo(res); |
| | | return rv; |
| | | } |
| | | |
| | | /* description: send data from the socket |
| | | * input args: |
| | | * $sock : socket context pointer |
| | | * $data : socket send data |
| | | * $bytes: socket send data bytes |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | int socket_send(socket_ctx_t *sock, char *data, int bytes) |
| | | { |
| | | int rv = 0; |
| | | int i = 0; |
| | | int left_bytes = bytes; |
| | | |
| | | if( !sock || !data || bytes<= 0 ) |
| | | return -1; |
| | | |
| | | while( left_bytes > 0 ) |
| | | { |
| | | rv=write(sock->fd, &data[i], left_bytes); |
| | | if( rv < 0 ) |
| | | { |
| | | log_info("socket[%d] write() failure: %s, close socket now\n", sock->fd, strerror(errno)); |
| | | socket_term(sock); |
| | | return -2; |
| | | } |
| | | else if( rv == left_bytes ) |
| | | { |
| | | log_info("socket send %d bytes data over\n", bytes); |
| | | return 0; |
| | | } |
| | | else |
| | | { |
| | | /* not send over this time, continue to send left data */ |
| | | i += rv; |
| | | left_bytes -= rv; |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* description: receive data from the socket |
| | | * input args: |
| | | * $sock : socket context pointer |
| | | * $buf : socket receive data buffer |
| | | * $size : socket receive data buffer size |
| | | * $timeout: receive data time, <=0 will don't timeout |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | int socket_recv(socket_ctx_t *sock, char *buf, int size, int timeout) |
| | | { |
| | | int rv = 0; |
| | | int i = 0; |
| | | fd_set rdset; |
| | | int maxfd; |
| | | |
| | | if( !sock || !buf || size<= 0 ) |
| | | return -1; |
| | | |
| | | memset(buf, 0, size); |
| | | |
| | | maxfd = sock->fd; |
| | | FD_ZERO(&rdset); |
| | | FD_SET(sock->fd, &rdset); |
| | | |
| | | if( timeout <= 0 ) /* no timeout */ |
| | | { |
| | | rv=select(maxfd+1, &rdset, NULL, NULL, NULL); |
| | | } |
| | | else |
| | | { |
| | | struct timeval tv; |
| | | tv.tv_sec = timeout; |
| | | tv.tv_usec = 0; |
| | | rv=select(maxfd+1, &rdset, NULL, NULL, &tv); |
| | | } |
| | | |
| | | if( rv < 0 ) |
| | | { |
| | | log_error("select() on socket[%d] got error: %s\n", sock->fd, strerror(errno)); |
| | | return -2; |
| | | } |
| | | else if( rv == 0 ) |
| | | { |
| | | log_error("select() on socket[%d] get timeout\n", sock->fd); |
| | | return 0; |
| | | } |
| | | else |
| | | { |
| | | rv = read(sock->fd, buf, size); |
| | | if( rv <= 0 ) |
| | | { |
| | | log_error("socket[%d] read() failure or got disconnected: %s, close socket now\n", sock->fd, strerror(errno)); |
| | | socket_term(sock); |
| | | return -2; |
| | | } |
| | | else |
| | | { |
| | | log_debug("socket[%d] receive %d bytes data\n", sock->fd, rv); |
| | | return rv; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /*+-------------------------------------------------------------------+ |
| | | *| socket utils function | |
| | | *+-------------------------------------------------------------------+*/ |
| | | |
| | | |
| | | /* socket connected or not: <0: failure 0:ok */ |
| | | int sock_check_connect(int sockfd) |
| | | { |
| | | struct tcp_info info; |
| | | int len=sizeof(info); |
| | | |
| | | if( sockfd < 0 ) |
| | | return -1; |
| | | |
| | | getsockopt(sockfd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len); |
| | | |
| | | if( TCP_CLOSE==info.tcpi_state || TCP_CLOSING==info.tcpi_state || TCP_CLOSE_WAIT==info.tcpi_state ) |
| | | { |
| | | return -3; |
| | | } |
| | | |
| | | return -0; |
| | | } |
| | | |
| | | /* description: set socket listen port as reusable, fix port already used bug */ |
| | | int socket_set_reuseaddr(int sockfd) |
| | | { |
| | | int opt = 1; |
| | | int len = sizeof (int); |
| | | |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, len)) |
| | | { |
| | | log_error("Set socket[%d] option SO_REUSEADDR failed:%s\n", sockfd, strerror(errno)); |
| | | return -1; |
| | | } |
| | | log_debug("Set socket[%d] option SO_REUSEADDR ok\n", sockfd); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* set socket as non-block mode, common socket default work as block mode */ |
| | | int socket_set_nonblock(int sockfd) |
| | | { |
| | | int opts; |
| | | /* |
| | | * fcntl may set: |
| | | * |
| | | * EACCES, EAGAIN: Operation is prohibited by locks held by other |
| | | * processes. Or, operation is prohibited because the file has |
| | | * been memory-mapped by another process. |
| | | * EBADF: fd is not an open file descriptor, or the command was F_SETLK |
| | | * or F_SETLKW and the file descriptor open mode doesn't match |
| | | * with the type of lock requested. |
| | | * EDEADLK: It was detected that the specified F_SETLKW command would |
| | | * cause a deadlock. |
| | | * EFAULT: lock is outside your accessible address space. |
| | | * EINTR: For F_SETLKW, the command was interrupted by a signal. For |
| | | * F_GETLK and F_SETLK, the command was interrupted by a signal |
| | | * before the lock was checked or acquired. Most likely when |
| | | * locking a remote file (e.g. locking over NFS), but can |
| | | * sometimes happen locally. |
| | | * EINVAL: For F_DUPFD, arg is negative or is greater than the maximum |
| | | * allowable value. For F_SETSIG, arg is not an allowable signal |
| | | * number. |
| | | * EMFILE: For F_DUPFD, the process already has the maximum number of |
| | | * file descriptors open. |
| | | * ENOLCK: Too many segment locks open, lock table is full, or a remote |
| | | * locking protocol failed (e.g. locking over NFS). |
| | | * EPERM: Attempted to clear the O_APPEND flag on a file that has the |
| | | * append-only attribute set. |
| | | */ |
| | | opts = fcntl(sockfd, F_GETFL); |
| | | if (opts < 0) |
| | | { |
| | | log_warn("fcntl() get socket options failure: %s\n", strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | opts |= O_NONBLOCK; |
| | | |
| | | if (fcntl(sockfd, F_SETFL, opts) < 0) |
| | | { |
| | | log_warn("fcntl() set socket options failure: %s\n", strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | log_debug("Set socket[%d] none blocking\n", sockfd); |
| | | return opts; |
| | | } |
| | | |
| | | |
| | | /* set socket receive and send buffer size in linux kernel space */ |
| | | int socket_set_buffer(int sockfd, int rsize, int ssize) |
| | | { |
| | | int opt; |
| | | socklen_t optlen = sizeof(opt); |
| | | |
| | | if(sockfd < 0) |
| | | return -1; |
| | | |
| | | /* Get system default receive buffer size, Linux X86: 85K */ |
| | | if (getsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, &optlen)) |
| | | { |
| | | log_warn("getsockopt() get receive buffer failure: %s\n", strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | /* Only when current receive buffer size larger than the default one will change it */ |
| | | if(rsize > opt) |
| | | { |
| | | opt = (int) rsize; |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, optlen)) |
| | | { |
| | | log_warn("setsockopt() set receive buffer to %d failure: %s\n", opt, strerror(errno)); |
| | | return -2; |
| | | } |
| | | } |
| | | |
| | | /* Get system default send buffer size, Linux X86: 16K */ |
| | | if (getsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, &optlen)) |
| | | { |
| | | log_warn("getsockopt() get send buffer failure: %s\n", strerror(errno)); |
| | | return -3; |
| | | } |
| | | |
| | | /* Only when current receive buffer size larger than the default one will change it */ |
| | | if(ssize > opt) |
| | | { |
| | | opt = (int) ssize; |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, optlen)) |
| | | { |
| | | log_warn("setsockopt() set send buffer to %d failure: %s\n", opt, strerror(errno)); |
| | | return -3; |
| | | } |
| | | } |
| | | |
| | | log_info("Set socket[%d] RCVBUF size:%d SNDBUF size:%d\n", sockfd, rsize, ssize); |
| | | return 0; |
| | | } |
| | | |
| | | /* |
| | | * Enable socket SO_KEEPALIVE, if the connection disconnected, any system call on socket |
| | | * will return immediately and errno will be set to "WSAENOTCONN" |
| | | * |
| | | * keepalive is not program related, but socket related, * so if you have multiple sockets, |
| | | * you can handle keepalive for each of them separately. |
| | | * |
| | | * Reference: http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/ |
| | | */ |
| | | int socket_set_keepalive(int sockfd, int keepintvl, int keepcnt) |
| | | { |
| | | int opt; |
| | | |
| | | if(sockfd < 0) |
| | | return -1; |
| | | |
| | | /* Enable the KEEPALIVE flag */ |
| | | opt = 1; |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_warn("setsockopt() enable SO_KEEPALIVE failure: %s\n", strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | if(keepintvl || keepcnt) |
| | | { |
| | | /* |
| | | * The tcp_keepidle parameter specifies the interval between the last data packet sent |
| | | * (simple ACKs are not considered data) and the first keepalive probe; after the |
| | | * connection is marked to need keepalive, this counter is not used any further. |
| | | * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_time |
| | | * 7200 |
| | | */ |
| | | opt = 3; /* 3 seconds */ |
| | | if (setsockopt (sockfd, SOL_TCP, TCP_KEEPIDLE, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_error("setsockopt() set TCP_KEEPIDLE to %d seconds failure: %s\n", opt, strerror(errno)); |
| | | return -3; |
| | | } |
| | | |
| | | if((opt=keepintvl) > 0) |
| | | { |
| | | /* |
| | | * The tcp_keepintvl parameter specifies the interval between subsequential keepalive |
| | | * probes, regardless of what the connection has exchanged in the meantime. |
| | | * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_intvl |
| | | * 75 |
| | | */ |
| | | if (setsockopt (sockfd, SOL_TCP, TCP_KEEPINTVL, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_error("setsockopt() set TCP_KEEPINTVL to %d failure: %s\n", opt, strerror(errno)); |
| | | return -4; |
| | | } |
| | | } |
| | | |
| | | if((opt=keepcnt) > 0) |
| | | { |
| | | /* |
| | | * The TCP_KEEPCNT option specifies the maximum number of unacknowledged probes to |
| | | * send before considering the connection dead and notifying the application layer |
| | | * probes to be sent. The value of TCP_KEEPCNT is an integer value between 1 and n, |
| | | * where n is the value of the systemwide tcp_keepcnt parameter. |
| | | * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_probes |
| | | * 9 |
| | | */ |
| | | if (setsockopt (sockfd, SOL_TCP, TCP_KEEPCNT, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_error("setsockopt() set TCP_KEEPCNT to %d failure: %s\n", opt, strerror(errno)); |
| | | return -5; |
| | | } |
| | | } |
| | | } |
| | | |
| | | log_debug("Set socket[%d] KEEPINTVL:%d KEEPCNT:%d\n", sockfd, keepintvl, keepcnt); |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | /* Set open file description count to max */ |
| | | void set_socket_rlimit(void) |
| | | { |
| | | struct rlimit limit = {0}; |
| | | |
| | | getrlimit(RLIMIT_NOFILE, &limit ); |
| | | limit.rlim_cur = limit.rlim_max; |
| | | setrlimit(RLIMIT_NOFILE, &limit ); |
| | | |
| | | log_info("set socket open fd max count to %d\n", limit.rlim_max); |
| | | } |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2022 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: socket.h |
| | | * Description: This head file is for socket API functions |
| | | * |
| | | * Version: 1.0.0(18/04/22) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "18/04/22 17:09:59" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef _SOCKET_H_ |
| | | #define _SOCKET_H_ |
| | | |
| | | #define HOSTNAME_LEN 64 |
| | | |
| | | typedef struct socket_ctx_s |
| | | { |
| | | char host[HOSTNAME_LEN]; /* CLIENT: Connect server hostname; SERVER: Unused */ |
| | | int port; /* CLIENT: Connect server port; SERVER: listen port */ |
| | | int fd; /* socket descriptor */ |
| | | } socket_ctx_t; |
| | | |
| | | /* description: initial socket context |
| | | * input args: |
| | | * $sock: socket context pointer |
| | | * $host: connect server hostname for client mode, unused for server mode |
| | | * $port: connect server port for client mode or listen port for server mode |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | extern int socket_init(socket_ctx_t *sock, char *host, int port); |
| | | |
| | | /* description: close socket |
| | | * input args: |
| | | * $sock: socket context pointer |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | extern int socket_term(socket_ctx_t *sock); |
| | | |
| | | /* description: socket server start listen |
| | | * input args: |
| | | * $sock: socket context pointer |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | extern int socket_listen(socket_ctx_t *sock); |
| | | |
| | | /* description: socket client connect to server |
| | | * input args: |
| | | * $sock: socket context pointer |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | extern int socket_connect(socket_ctx_t *sock); |
| | | |
| | | /* description: send data from the socket |
| | | * input args: |
| | | * $sock : socket context pointer |
| | | * $data : socket send data |
| | | * $bytes: socket send data bytes |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | extern int socket_send(socket_ctx_t *sock, char *data, int bytes); |
| | | |
| | | /* description: receive data from the socket |
| | | * input args: |
| | | * $sock : socket context pointer |
| | | * $buf : socket receive data buffer |
| | | * $size : socket receive data buffer size |
| | | * $timeout: receive data time, <=0 will don't timeout |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | #define TIMEOUT_NONE 0 |
| | | extern int socket_recv(socket_ctx_t *sock, char *buf, int size, int timeout); |
| | | |
| | | /*+-------------------------------------------------------------------+ |
| | | *| socket utils function | |
| | | *+-------------------------------------------------------------------+*/ |
| | | |
| | | |
| | | /* socket connected or not: <0: failure 0:ok */ |
| | | extern int sock_check_connect(int sockfd); |
| | | |
| | | /* description: set socket listen port as reusable, fix port already used bug */ |
| | | extern int socket_set_reuseaddr(int sockfd); |
| | | |
| | | /* set socket as non-block mode, common socket default work as block mode */ |
| | | extern int socket_set_nonblock(int sockfd); |
| | | |
| | | /* set socket receive and send buffer size in linux kernel space */ |
| | | extern int socket_set_buffer(int sockfd, int rsize, int ssize); |
| | | |
| | | /* set heartbeat keepalive */ |
| | | extern int socket_set_keepalive(int sockfd, int keepintvl, int keepcnt); |
| | | |
| | | /* Set open file description count to max */ |
| | | extern void set_socket_rlimit(void); |
| | | |
| | | #endif /* ----- #ifndef _SOCKET_H_ ----- */ |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: sqlite_blob.c |
| | | * Description: This library used to operate blob packet in sqlite database. |
| | | * |
| | | * Version: 1.0.0(2020年05月13日) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2020年05月13日 12时14分23秒" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <string.h> |
| | | #include "sqlite_blob.h" |
| | | #include "logger.h" |
| | | |
| | | /* Blob packet table name */ |
| | | #define TABLE_NAME "PackTable" |
| | | |
| | | /* Use static global handler here in order to simplify the API, |
| | | * But it will make this library not thread safe |
| | | */ |
| | | static sqlite3 *s_clidb = NULL; |
| | | |
| | | |
| | | /* description: open or create sqlite database if not exist |
| | | * input args: |
| | | * $db_file: sqlite database file name |
| | | * return value: <0: failure 0:ok |
| | | * */ |
| | | int database_init(const char *db_file) |
| | | { |
| | | char sql[SQL_COMMAND_LEN]={0}; |
| | | char *errmsg = NULL; |
| | | |
| | | if( !db_file ) |
| | | { |
| | | log_error("%s() Invalid input arguments\n", __func__); |
| | | return -1; |
| | | } |
| | | |
| | | /*+------------------------------------------+ |
| | | *| database already exist, just open it | |
| | | *+------------------------------------------+*/ |
| | | if( 0==access(db_file, F_OK) ) |
| | | { |
| | | if( SQLITE_OK != sqlite3_open(db_file, &s_clidb) ) |
| | | { |
| | | log_error("open database file '%s' failure\n", db_file); |
| | | return -2; |
| | | } |
| | | log_info("open database file '%s' ok\n", db_file); |
| | | return 0; |
| | | } |
| | | |
| | | /*+-----------------------------------------+ |
| | | *| database not exist, create and init it | |
| | | *+-----------------------------------------+*/ |
| | | |
| | | if( SQLITE_OK != sqlite3_open(db_file, &s_clidb) ) |
| | | { |
| | | log_error("create database file '%s' failure\n", db_file); |
| | | return -2; |
| | | } |
| | | |
| | | /* SQLite continues without syncing as soon as it has handed data off to the operating system */ |
| | | sqlite3_exec(s_clidb, "pragma synchronous = OFF; ", NULL, NULL, NULL); |
| | | |
| | | /* enable full auto vacuum, Auto increase/decrease */ |
| | | sqlite3_exec(s_clidb, "pragma auto_vacuum = 2 ; ", NULL, NULL, NULL); |
| | | |
| | | /* Create firehost table in the database */ |
| | | snprintf(sql, sizeof(sql), "CREATE TABLE %s(packet BLOB);", TABLE_NAME); |
| | | if( SQLITE_OK != sqlite3_exec(s_clidb, sql, NULL, NULL, &errmsg) ) |
| | | { |
| | | log_error("create data_table in database file '%s' failure: %s\n", db_file, errmsg); |
| | | sqlite3_free(errmsg); /* free errmsg */ |
| | | sqlite3_close(s_clidb); /* close databse */ |
| | | unlink(db_file); /* remove database file */ |
| | | return -3; |
| | | } |
| | | |
| | | log_info("create and init database file '%s' ok\n", db_file); |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | /* description: close sqlite database handler |
| | | * return value: none |
| | | */ |
| | | void database_term(void) |
| | | { |
| | | log_warn("close sqlite database now\n"); |
| | | sqlite3_close(s_clidb); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | |
| | | /* description: push a blob packet into database |
| | | * input args: |
| | | * $pack: blob packet data address |
| | | * $size: blob packet data bytes |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | int blobdb_push_packet(void *pack, int size) |
| | | { |
| | | char sql[SQL_COMMAND_LEN]={0}; |
| | | int rv = 0; |
| | | char *errmsg = NULL; |
| | | sqlite3_stmt *stat = NULL; |
| | | |
| | | if( !pack || size<=0 ) |
| | | { |
| | | log_error("%s() Invalid input arguments\n", __func__); |
| | | return -1; |
| | | } |
| | | |
| | | if( ! s_clidb ) |
| | | { |
| | | log_error("sqlite database not opened\n"); |
| | | return -2; |
| | | } |
| | | |
| | | snprintf(sql, sizeof(sql), "insert into %s(packet) values(?)", TABLE_NAME); |
| | | rv = sqlite3_prepare_v2(s_clidb, sql, -1, &stat, NULL); |
| | | if(SQLITE_OK!=rv || !stat) |
| | | { |
| | | log_error("blob add sqlite3_prepare_v2 failure\n"); |
| | | rv = -2; |
| | | goto OUT; |
| | | } |
| | | |
| | | if( SQLITE_OK != sqlite3_bind_blob(stat, 1, pack, size, NULL) ) |
| | | { |
| | | log_error("blob add sqlite3_bind_blob failure\n"); |
| | | rv = -3; |
| | | goto OUT; |
| | | } |
| | | |
| | | rv = sqlite3_step(stat); |
| | | if( SQLITE_DONE!=rv && SQLITE_ROW!=rv ) |
| | | { |
| | | log_error("blob add sqlite3_step failure\n"); |
| | | rv = -4; |
| | | goto OUT; |
| | | } |
| | | |
| | | OUT: |
| | | sqlite3_finalize(stat); |
| | | |
| | | if( rv < 0 ) |
| | | log_error("add new blob packet into database failure, rv=%d\n", rv); |
| | | else |
| | | log_info("add new blob packet into database ok\n"); |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | /* description: pop the first blob packet from database |
| | | * input args: |
| | | * $pack: blob packet output buffer address |
| | | * $size: blob packet output buffer size |
| | | * $byte: blob packet bytes |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | int blobdb_pop_packet(void *pack, int size, int *bytes) |
| | | { |
| | | char sql[SQL_COMMAND_LEN]={0}; |
| | | int rv = 0; |
| | | sqlite3_stmt *stat = NULL; |
| | | const void *blob_ptr; |
| | | |
| | | if( !pack || size<=0 ) |
| | | { |
| | | log_error("%s() Invalid input arguments\n", __func__); |
| | | return -1; |
| | | } |
| | | |
| | | if( ! s_clidb ) |
| | | { |
| | | log_error("sqlite database not opened\n"); |
| | | return -2; |
| | | } |
| | | |
| | | /* Only query the first packet record */ |
| | | snprintf(sql, sizeof(sql), "select packet from %s limit 0,1;", TABLE_NAME); |
| | | rv = sqlite3_prepare_v2(s_clidb, sql, -1, &stat, NULL); |
| | | if(SQLITE_OK!=rv || !stat) |
| | | { |
| | | log_error("firehost sqlite3_prepare_v2 failure\n"); |
| | | rv = -3; |
| | | goto out; |
| | | } |
| | | |
| | | rv = sqlite3_step(stat); |
| | | if( SQLITE_DONE!=rv && SQLITE_ROW!=rv ) |
| | | { |
| | | log_error("firehost sqlite3_step failure\n"); |
| | | rv = -5; |
| | | goto out; |
| | | } |
| | | |
| | | /* 1rd argument<0> means first segement is packet */ |
| | | blob_ptr = sqlite3_column_blob(stat, 0); |
| | | if( !blob_ptr ) |
| | | { |
| | | rv = -6; |
| | | goto out; |
| | | } |
| | | |
| | | *bytes = sqlite3_column_bytes(stat, 0); |
| | | |
| | | if( *bytes > size ) |
| | | { |
| | | log_error("blob packet bytes[%d] larger than bufsize[%d]\n", *bytes, size); |
| | | *bytes = 0; |
| | | rv = -1; |
| | | } |
| | | |
| | | memcpy(pack, blob_ptr, *bytes); |
| | | rv = 0; |
| | | |
| | | out: |
| | | sqlite3_finalize(stat); |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | /* description: remove the first blob packet from database |
| | | * input args: none |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | int blobdb_del_packet(void) |
| | | { |
| | | char sql[SQL_COMMAND_LEN]={0}; |
| | | char *errmsg = NULL; |
| | | |
| | | if( ! s_clidb ) |
| | | { |
| | | log_error("sqlite database not opened\n"); |
| | | return -2; |
| | | } |
| | | |
| | | /* remove packet from db */ |
| | | memset(sql, 0, sizeof(sql)); |
| | | snprintf(sql, sizeof(sql), "delete from %s limit 0,1;", TABLE_NAME); |
| | | if( SQLITE_OK != sqlite3_exec(s_clidb, sql, NULL, 0, &errmsg) ) |
| | | { |
| | | log_error("delete first blob packet from database failure: %s\n", errmsg); |
| | | sqlite3_free(errmsg); |
| | | return -2; |
| | | } |
| | | log_warn("delete first blob packet from database ok\n"); |
| | | |
| | | /* Vacuum the database */ |
| | | sqlite3_exec(s_clidb, "VACUUM;", NULL, 0, NULL); |
| | | |
| | | return 0; |
| | | } |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: sqlite_blob.h |
| | | * Description: This library used to operate blob packet in sqlite database. |
| | | * |
| | | * Version: 1.0.0(2020年05月13日) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2020年05月13日 12时14分23秒" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef _SQLITE_BLOB_H_ |
| | | #define _SQLITE_BLOB_H_ |
| | | |
| | | #include "sqlite3.h" |
| | | |
| | | #define SQL_COMMAND_LEN 256 |
| | | |
| | | /* description: open or create sqlite database if not exist |
| | | * input args: |
| | | * $db_file: sqlite database file name |
| | | * return value: <0: failure 0:ok |
| | | * */ |
| | | extern int database_init(const char *db_file); |
| | | |
| | | |
| | | /* description: close sqlite database handler |
| | | * return value: none |
| | | */ |
| | | extern void database_term(void); |
| | | |
| | | |
| | | /* description: push a blob packet into database |
| | | * input args: |
| | | * $pack: blob packet data address |
| | | * $size: blob packet data bytes |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | extern int blobdb_push_packet(void *pack, int size); |
| | | |
| | | |
| | | /* description: pop the first blob packet from database |
| | | * input args: |
| | | * $pack: blob packet output buffer address |
| | | * $size: blob packet output buffer size |
| | | * $byte: blob packet bytes |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | extern int blobdb_pop_packet(void *pack, int size, int *bytes); |
| | | |
| | | |
| | | /* description: remove the first blob packet from database |
| | | * input args: none |
| | | * return value: <0: failure 0:ok |
| | | */ |
| | | extern int blobdb_del_packet(void); |
| | | |
| | | |
| | | #endif /* ----- #ifndef _SQLITE_BLOB_H_ ----- */ |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: util_proc.c |
| | | * Description: This file is the process API |
| | | * |
| | | * Version: 1.0.0(7/06/2020) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "7/06/2020 09:19:02 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <unistd.h> |
| | | #include <libgen.h> |
| | | #include <errno.h> |
| | | #include <fcntl.h> |
| | | #include <stdarg.h> |
| | | #include <sys/types.h> |
| | | #include <sys/stat.h> |
| | | #include <pthread.h> |
| | | |
| | | #include "util_proc.h" |
| | | #include "logger.h" |
| | | |
| | | proc_signal_t g_signal={0}; |
| | | |
| | | void proc_default_sighandler(int sig) |
| | | { |
| | | switch(sig) |
| | | { |
| | | case SIGINT: |
| | | log_warn("SIGINT - stopping\n"); |
| | | g_signal.stop = 1; |
| | | break; |
| | | |
| | | case SIGTERM: |
| | | log_warn("SIGTERM - stopping\n"); |
| | | g_signal.stop = 1; |
| | | break; |
| | | |
| | | case SIGSEGV: |
| | | log_warn("SIGSEGV - stopping\n"); |
| | | #if 0 |
| | | if(g_signal.stop) |
| | | exit(0); |
| | | |
| | | g_signal.stop = 1; |
| | | #endif |
| | | break; |
| | | |
| | | case SIGPIPE: |
| | | log_warn("SIGPIPE - warnning\n"); |
| | | break; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | |
| | | /* install default signal process functions */ |
| | | void install_default_signal(void) |
| | | { |
| | | struct sigaction sigact, sigign; |
| | | |
| | | log_info("Install default signal handler.\n"); |
| | | |
| | | /* Initialize the catch signal structure. */ |
| | | sigemptyset(&sigact.sa_mask); |
| | | sigact.sa_flags = 0; |
| | | sigact.sa_handler = proc_default_sighandler; |
| | | |
| | | /* Setup the ignore signal. */ |
| | | sigemptyset(&sigign.sa_mask); |
| | | sigign.sa_flags = 0; |
| | | sigign.sa_handler = SIG_IGN; |
| | | |
| | | sigaction(SIGTERM, &sigact, 0); /* catch terminate signal "kill" command */ |
| | | sigaction(SIGINT, &sigact, 0); /* catch interrupt signal CTRL+C */ |
| | | //sigaction(SIGSEGV, &sigact, 0); /* catch segmentation faults */ |
| | | sigaction(SIGPIPE, &sigact, 0); /* catch broken pipe */ |
| | | #if 0 |
| | | sigaction(SIGCHLD, &sigact, 0); /* catch child process return */ |
| | | sigaction(SIGUSR2, &sigact, 0); /* catch USER signal */ |
| | | #endif |
| | | } |
| | | |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: daemonize |
| | | * Description : Set the programe runs as daemon in background |
| | | * Inputs : nodir: DON'T change the work directory to / : 1:NoChange 0:Change |
| | | * noclose: close the opened file descrtipion or not 1:Noclose 0:Close |
| | | * Output : NONE |
| | | * Return : NONE |
| | | * *****************************************************************************/ |
| | | void daemonize(int nochdir, int noclose) |
| | | { |
| | | int rv, fd; |
| | | int i; |
| | | |
| | | /* already a daemon */ |
| | | if (1 == getppid()) |
| | | return; |
| | | |
| | | /* fork error */ |
| | | rv = fork(); |
| | | if (rv < 0) exit(1); |
| | | |
| | | /* parent process exit */ |
| | | if (rv > 0) |
| | | exit(0); |
| | | |
| | | /* obtain a new process session group */ |
| | | setsid(); |
| | | |
| | | if (!noclose) |
| | | { |
| | | /* close all descriptors */ |
| | | for (i = getdtablesize(); i >= 0; --i) |
| | | { |
| | | //if (i != g_logPtr->fd) |
| | | close(i); |
| | | } |
| | | |
| | | /* Redirect Standard input [0] to /dev/null */ |
| | | fd = open("/dev/null", O_RDWR); |
| | | |
| | | /* Redirect Standard output [1] to /dev/null */ |
| | | dup(fd); |
| | | |
| | | /* Redirect Standard error [2] to /dev/null */ |
| | | dup(fd); |
| | | } |
| | | |
| | | umask(0); |
| | | |
| | | if (!nochdir) |
| | | chdir("/"); |
| | | |
| | | return; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: check_set_program_running |
| | | * Description : check program already running or not, if not then run it and |
| | | * record pid into $pidfile |
| | | * Inputs : daemon: set program running in daemon or not |
| | | * pid_file:The record PID file path |
| | | * Output : NONE |
| | | * Return : 0: Record successfully Else: Failure |
| | | * *****************************************************************************/ |
| | | |
| | | int check_set_program_running(int daemon, char *pidfile) |
| | | { |
| | | if( !pidfile ) |
| | | return 0; |
| | | |
| | | if( check_daemon_running(pidfile) ) |
| | | { |
| | | log_error("Program already running, process exit now"); |
| | | return -1; |
| | | } |
| | | |
| | | if( daemon ) |
| | | { |
| | | if( set_daemon_running(pidfile) < 0 ) |
| | | { |
| | | log_error("set program running as daemon failure\n"); |
| | | return -2; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if( record_daemon_pid(pidfile) < 0 ) |
| | | { |
| | | log_error("record program running PID failure\n"); |
| | | return -3; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: record_daemon_pid |
| | | * Description : Record the running daemon program PID to the file "pid_file" |
| | | * Inputs : pid_file:The record PID file path |
| | | * Output : NONE |
| | | * Return : 0: Record successfully Else: Failure |
| | | * *****************************************************************************/ |
| | | int record_daemon_pid(const char *pid_file) |
| | | { |
| | | struct stat fStatBuf; |
| | | int fd = -1; |
| | | int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU; |
| | | char ipc_dir[64] = { 0 }; |
| | | |
| | | strncpy(ipc_dir, pid_file, 64); |
| | | |
| | | /* dirname() will modify ipc_dir and save the result */ |
| | | dirname(ipc_dir); |
| | | |
| | | /* If folder pid_file PATH doesnot exist, then we will create it" */ |
| | | if (stat(ipc_dir, &fStatBuf) < 0) |
| | | { |
| | | if (mkdir(ipc_dir, mode) < 0) |
| | | { |
| | | log_error("cannot create %s: %s\n", ipc_dir, strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | (void)chmod(ipc_dir, mode); |
| | | } |
| | | |
| | | /* Create the process running PID file */ |
| | | mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; |
| | | if ((fd = open(pid_file, O_RDWR | O_CREAT | O_TRUNC, mode)) >= 0) |
| | | { |
| | | char pid[PID_ASCII_SIZE]; |
| | | snprintf(pid, sizeof(pid), "%u\n", (unsigned)getpid()); |
| | | write(fd, pid, strlen(pid)); |
| | | close(fd); |
| | | |
| | | log_debug("Record PID<%u> to file %s.\n", getpid(), pid_file); |
| | | } |
| | | else |
| | | { |
| | | log_error("cannot create %s: %s\n", pid_file, strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: get_daemon_pid |
| | | * Description : Get the daemon process PID from the PID record file "pid_file" |
| | | * Inputs : pid_file: the PID record file |
| | | * Output : NONE |
| | | * Return : pid_t: The daemon process PID number |
| | | * *****************************************************************************/ |
| | | pid_t get_daemon_pid(const char *pid_file) |
| | | { |
| | | FILE *f; |
| | | pid_t pid; |
| | | |
| | | if ((f = fopen(pid_file, "rb")) != NULL) |
| | | { |
| | | char pid_ascii[PID_ASCII_SIZE]; |
| | | (void)fgets(pid_ascii, PID_ASCII_SIZE, f); |
| | | (void)fclose(f); |
| | | pid = atoi(pid_ascii); |
| | | } |
| | | else |
| | | { |
| | | log_error("Can't open PID record file %s: %s\n", pid_file, strerror(errno)); |
| | | return -1; |
| | | } |
| | | return pid; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: check_daemon_running |
| | | * Description : Check the daemon program already running or not |
| | | * Inputs : pid_file: The record running daemon program PID |
| | | * Output : NONE |
| | | * Return : 1: The daemon program alread running 0: Not running |
| | | * *****************************************************************************/ |
| | | int check_daemon_running(const char *pid_file) |
| | | { |
| | | int rv = -1; |
| | | struct stat fStatBuf; |
| | | |
| | | rv = stat(pid_file, &fStatBuf); |
| | | if (0 == rv) |
| | | { |
| | | pid_t pid = -1; |
| | | printf("PID record file \"%s\" exist.\n", pid_file); |
| | | |
| | | pid = get_daemon_pid(pid_file); |
| | | if (pid > 0) /* Process pid exist */ |
| | | { |
| | | if ((rv = kill(pid, 0)) == 0) |
| | | { |
| | | printf("Program with PID[%d] seems running.\n", pid); |
| | | return 1; |
| | | } |
| | | else /* Send signal to the old process get no reply. */ |
| | | { |
| | | printf("Program with PID[%d] seems exit.\n", pid); |
| | | remove(pid_file); |
| | | return 0; |
| | | } |
| | | } |
| | | else if (0 == pid) |
| | | { |
| | | printf("Can not read program PID form record file.\n"); |
| | | remove(pid_file); |
| | | return 0; |
| | | } |
| | | else /* Read pid from file "pid_file" failure */ |
| | | { |
| | | printf("Read record file \"%s\" failure, maybe program still running.\n", pid_file); |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: stop_daemon_running |
| | | * Description : Stop the daemon program running |
| | | * Inputs : pid_file: The record running daemon program PID |
| | | * Output : NONE |
| | | * Return : 1: The daemon program alread running 0: Not running |
| | | * *****************************************************************************/ |
| | | int stop_daemon_running(const char *pid_file) |
| | | { |
| | | pid_t pid = -1; |
| | | struct stat fStatBuf; |
| | | |
| | | if ( stat(pid_file, &fStatBuf) < 0) |
| | | return 0; |
| | | |
| | | printf("PID record file \"%s\" exist.\n", pid_file); |
| | | pid = get_daemon_pid(pid_file); |
| | | if (pid > 0) /* Process pid exist */ |
| | | { |
| | | while ( (kill(pid, 0) ) == 0) |
| | | { |
| | | kill(pid, SIGTERM); |
| | | sleep(1); |
| | | } |
| | | |
| | | remove(pid_file); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* **************************************************************************** |
| | | * FunctionName: set_daemon_running |
| | | * Description : Set the programe running as daemon if it's not running and record |
| | | * its PID to the pid_file. |
| | | * Inputs : pid_file: The record running daemon program PID |
| | | * Output : NONE |
| | | * Return : 0: Successfully. 1: Failure |
| | | * *****************************************************************************/ |
| | | int set_daemon_running(const char *pid_file) |
| | | { |
| | | daemon(1, 1); |
| | | log_info("Program running as daemon [PID:%d].\n", getpid()); |
| | | |
| | | if (record_daemon_pid(pid_file) < 0) |
| | | { |
| | | log_error("Record PID to file \"%s\" failure.\n", pid_file); |
| | | return -2; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* start a new thread to run $thread_workbody point function */ |
| | | int thread_start(pthread_t *thread_id, thread_body_t thread_workbody, void *thread_arg) |
| | | { |
| | | int rv = 0; |
| | | pthread_t tid; |
| | | |
| | | pthread_attr_t thread_attr; |
| | | |
| | | /* Initialize the thread attribute */ |
| | | rv = pthread_attr_init(&thread_attr); |
| | | if(rv) |
| | | return -1; |
| | | |
| | | #if 0 |
| | | /* Set the stack size of the thread */ |
| | | rv = pthread_attr_setstacksize(&thread_attr, 120 * 1024); |
| | | if(rv) |
| | | goto CleanUp; |
| | | #endif |
| | | |
| | | /* Set thread to detached state:Don`t need pthread_join */ |
| | | rv = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); |
| | | if(rv) |
| | | goto CleanUp; |
| | | |
| | | /* Create the thread */ |
| | | rv = pthread_create(&tid, &thread_attr, thread_workbody, thread_arg); |
| | | if(rv) |
| | | goto CleanUp; |
| | | |
| | | CleanUp: |
| | | |
| | | |
| | | if( thread_id ) |
| | | { |
| | | if( rv ) |
| | | *thread_id = 0; |
| | | else |
| | | *thread_id = tid; |
| | | } |
| | | |
| | | /* Destroy the attributes of thread */ |
| | | pthread_attr_destroy(&thread_attr); |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | /* excute a linux command by system() */ |
| | | void exec_system_cmd(const char *format, ...) |
| | | { |
| | | char cmd[256]; |
| | | va_list args; |
| | | |
| | | memset(cmd, 0, sizeof(cmd)); |
| | | |
| | | va_start(args, format); |
| | | vsnprintf(cmd, sizeof(cmd), format, args); |
| | | va_end(args); |
| | | |
| | | system(cmd); |
| | | } |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: util_proc.h |
| | | * Description: This head file is for Linux process/thread API |
| | | * |
| | | * Version: 1.0.0(7/06/2012~) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "7/06/2012 09:21:33 PM" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef __UTIL_PROC_H_ |
| | | #define __UTIL_PROC_H_ |
| | | |
| | | #include <signal.h> |
| | | |
| | | #define PID_ASCII_SIZE 11 |
| | | |
| | | typedef struct proc_signal_s |
| | | { |
| | | int signal; |
| | | unsigned stop; /* 0: Not term 1: Stop */ |
| | | } proc_signal_t; |
| | | |
| | | typedef void *(* thread_body_t) (void *thread_arg); |
| | | |
| | | extern proc_signal_t g_signal; |
| | | |
| | | /* install default signal process functions */ |
| | | extern void install_default_signal(void); |
| | | |
| | | /* excute a linux command by system() */ |
| | | extern void exec_system_cmd(const char *format, ...); |
| | | |
| | | /* check program already running or not, if not then run it and record pid into $pidfile */ |
| | | extern int check_set_program_running(int daemon, char *pidfile); |
| | | |
| | | /* stop program running from $pid_file */ |
| | | extern int stop_daemon_running(const char *pid_file); |
| | | |
| | | /* my implementation for set program running in daemon */ |
| | | extern void daemonize(int nochdir, int noclose); |
| | | |
| | | /* start a new thread to run $thread_workbody point function */ |
| | | extern int thread_start(pthread_t *thread_id, thread_body_t thread_workbody, void *thread_arg); |
| | | |
| | | /* +---------------------+ |
| | | * | Low level API | |
| | | * +---------------------+*/ |
| | | |
| | | /* record proces ID into $pid_file */ |
| | | extern int record_daemon_pid(const char *pid_file); |
| | | |
| | | /* get daemon process ID from $pid_file */ |
| | | extern pid_t get_daemon_pid(const char *pid_file); |
| | | |
| | | /* check program already running or not from $pid_file */ |
| | | extern int check_daemon_running(const char *pid_file); |
| | | |
| | | /* set program daemon running and record pid in $pid_file */ |
| | | extern int set_daemon_running(const char *pid_file); |
| | | |
| | | #endif |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: util_time.h |
| | | * Description: This head file is system time, timer API |
| | | * |
| | | * Version: 1.0.0(07/23/2020) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "07/23/2020 07:46:37 AM" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef __UTIL_TIME_H_ |
| | | #define __UTIL_TIME_H_ |
| | | |
| | | #include <unistd.h> |
| | | #include <stdint.h> |
| | | #include <string.h> |
| | | #include <fcntl.h> |
| | | #include <time.h> |
| | | |
| | | #include <linux/rtc.h> |
| | | #include <sys/ioctl.h> |
| | | #include <sys/types.h> |
| | | #include <sys/stat.h> |
| | | #include <sys/time.h> |
| | | |
| | | |
| | | typedef struct date_time_s |
| | | { |
| | | int year; |
| | | int month; |
| | | int day; |
| | | int hour; |
| | | int minute; |
| | | int second; |
| | | int dayofweek; |
| | | } date_time_t; |
| | | |
| | | /* sleep for micro second */ |
| | | static inline void msleep(unsigned long ms) |
| | | { |
| | | struct timespec timeout; |
| | | unsigned long tmp; |
| | | |
| | | timeout.tv_sec = ms / 1000; |
| | | if (timeout.tv_sec == 0) |
| | | { |
| | | tmp = ms * 10000; |
| | | timeout.tv_nsec = tmp * 100; |
| | | } |
| | | else |
| | | { |
| | | timeout.tv_nsec = 0; |
| | | } |
| | | |
| | | nanosleep(&timeout, 0); |
| | | } |
| | | |
| | | /* call gettimeofday() to get current micro second */ |
| | | static inline unsigned long time_now() |
| | | { |
| | | struct timeval now; |
| | | |
| | | gettimeofday(&now, 0); |
| | | |
| | | return (now.tv_sec*1000) + (now.tv_usec/1000); |
| | | } |
| | | |
| | | /* timep has elapsed since $start, unit as micro second*/ |
| | | static inline uint32_t time_elapsed(uint32_t start) |
| | | { |
| | | uint32_t current = time_now(); |
| | | |
| | | if(current >= start) |
| | | return current-start; |
| | | else |
| | | return current+0xFFFFFFFF-start; |
| | | } |
| | | |
| | | /* call gettimeofday() to get current micro second */ |
| | | static inline unsigned long time_second() |
| | | { |
| | | struct timeval now; |
| | | |
| | | gettimeofday(&now, 0); |
| | | return now.tv_sec; |
| | | } |
| | | |
| | | /* timep has elapsed since $start, unit as micro second*/ |
| | | static inline uint32_t seconds_elapsed(uint32_t start) |
| | | { |
| | | uint32_t current = time_second(); |
| | | |
| | | if(current >= start) |
| | | return current-start; |
| | | else |
| | | return current+0xFFFFFFFF-start; |
| | | } |
| | | |
| | | /* |
| | | * These inlines deal with timer wrapping correctly. You are |
| | | * strongly encouraged to use them |
| | | * 1. Because people otherwise forget |
| | | * 2. Because if the timer wrap changes in future you won't have to |
| | | * alter your driver code. |
| | | * |
| | | * time_after(a,b) returns true if the time a is after time b. |
| | | * |
| | | * Do this with "<0" and ">=0" to only test the sign of the result. A |
| | | * good compiler would generate better code (and a really good compiler |
| | | * wouldn't care). Gcc is currently neither. |
| | | */ |
| | | |
| | | #define typecheck(type,x) \ |
| | | ({ type __dummy; \ |
| | | typeof(x) __dummy2; \ |
| | | (void)(&__dummy == &__dummy2); \ |
| | | 1; \ |
| | | }) |
| | | |
| | | #define time_after(a,b) \ |
| | | (typecheck(unsigned long, a) && typecheck(unsigned long, b) && ((long)(b) - (long)(a) < 0)) |
| | | #define time_before(a,b) time_after(b,a) |
| | | |
| | | #define time_after_eq(a,b) \ |
| | | (typecheck(unsigned long, a) && typecheck(unsigned long, b) && ((long)(a) - (long)(b) >= 0)) |
| | | #define time_before_eq(a,b) time_after_eq(b,a) |
| | | |
| | | /* Same as above, but does so with platform independent 64bit types. |
| | | * These must be used when utilizing jiffies_64 (i.e. return value of |
| | | * get_jiffies_64() */ |
| | | #define time_after64(a,b) \ |
| | | (typecheck(__u64, a) && typecheck(__u64, b) && ((__s64)(b) - (__s64)(a) < 0)) |
| | | #define time_before64(a,b) time_after64(b,a) |
| | | |
| | | #define time_after_eq64(a,b) \ |
| | | (typecheck(__u64, a) && typecheck(__u64, b) && ((__s64)(a) - (__s64)(b) >= 0)) |
| | | #define time_before_eq64(a,b) time_after_eq64(b,a) |
| | | |
| | | |
| | | static inline void get_sys_time(date_time_t *date) |
| | | { |
| | | time_t now = time(NULL); |
| | | struct tm *tnow = localtime(&now); |
| | | |
| | | memset(date, 0, sizeof(*date)); |
| | | date->year = 1900 + tnow->tm_year; |
| | | date->month = 1 + tnow->tm_mon; |
| | | date->day = tnow->tm_mday; |
| | | |
| | | date->hour = tnow->tm_hour; |
| | | date->minute = tnow->tm_min; |
| | | date->second = tnow->tm_sec; |
| | | date->dayofweek = tnow->tm_wday; |
| | | return; |
| | | } |
| | | |
| | | static inline int get_rtc_time(date_time_t *date) |
| | | { |
| | | int rv, fd = -1; |
| | | struct rtc_time rtc_tm; |
| | | |
| | | memset(date, 0, sizeof(*date)); |
| | | |
| | | if ((fd=open("/dev/rtc0", O_RDONLY)) < 0) |
| | | return -1; |
| | | |
| | | if((rv=ioctl(fd, RTC_RD_TIME, &rtc_tm)) < 0) |
| | | return -2; |
| | | |
| | | date->year = 1900 + rtc_tm.tm_year; |
| | | date->month = 1 + rtc_tm.tm_mon; |
| | | date->day = rtc_tm.tm_mday; |
| | | |
| | | date->hour = rtc_tm.tm_hour; |
| | | date->minute = rtc_tm.tm_min; |
| | | date->second = rtc_tm.tm_sec; |
| | | date->dayofweek = rtc_tm.tm_wday; |
| | | |
| | | close(fd); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | #endif |
| | |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2018/10/14 12:13:26" |
| | | * |
| | | * |
| | | * Pin connection: |
| | | * |
| | | * vcc --- #Pin1 ( 3.3v ) |
| | | * DQ --- #Pin7 (BCM GPIO4) |
| | | * GND --- #Pin9 ( GND ) |
| | | * |
| | | * /boot/config.txt: |
| | | * |
| | | * dtoverlay=w1-gpio-pullup,gpiopin=4 |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | |
| | | if( argc != 3 ) |
| | | { |
| | | printf(" Usage: sudo %s [BCM Pin number] [1/0]\n", argv[0]); |
| | | printf("example, turn BCM Pin #6 lowlevel : sudo %s 6 0\n", argv[0]); |
| | | printf("example, turn BCM Pin #6 highlevel: sudo %s 6 1\n", argv[0]); |
| | | printf("example, turn BCM Pin #19 lowlevel : sudo %s 19 0\n", argv[0]); |
| | | printf("example, turn BCM Pin #19 highlevel: sudo %s 19 1\n", argv[0]); |
| | | return 0; |
| | | } |
| | | |
| | | bcm_pin = atoi(argv[1]); |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2018 LingYun IoT System Studio |
| | | * Copyright: (C) 2021 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: led.c |
| | | * Description: This file is used to control RGB 3-colours LED |
| | | * Description: This file is used to control RGB 3-colors LED |
| | | * |
| | | * pi@raspberrypi:~ $ gpio readall show BCM and wPi pinmap |
| | | * pi@raspberrypi:~ $ gpio readall #show RPi pin map |
| | | * |
| | | * LED BCM wPi |
| | | * G ---- GPIO.13 ---- GPIO.23 |
| | | * R ---- GPIO.19 ---- GPIO.24 |
| | | * B ---- GPIO.26 ---- GPIO.25 |
| | | * I ---- GND ---- |
| | | * LED #PIN BCM |
| | | * I ---- 39 ---- GND |
| | | * G ---- 37 ---- GPIO26 |
| | | * R ---- 35 ---- GPIO19 |
| | | * B ---- 33 ---- GPIO13 |
| | | * |
| | | * Version: 1.0.0(2018/10/14) |
| | | * Version: 1.0.0(2012/11/03) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2018/10/14 12:13:26" |
| | | * ChangeLog: 1, Release initial version on "2021/11/03 12:13:26" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | |
| | | #include <time.h> |
| | | #include <errno.h> |
| | | |
| | | #include "led.h" |
| | | #include <gpiod.h> |
| | | |
| | | #define msleep(x) usleep( 1000*(x) ) |
| | | #define DELAY 500 |
| | | |
| | | #define ON 1 |
| | | #define OFF 0 |
| | | |
| | | /* Three LEDs code */ |
| | | enum |
| | | { |
| | | LED_R = 0, |
| | | LED_G, |
| | | LED_B, |
| | | LED_MAX, |
| | | }; |
| | | |
| | | /* RGB 3-color LED BCM pin number */ |
| | | static int led_gpio[LED_MAX]= { 19, 26, 13 }; |
| | | |
| | | void init_led(void); |
| | | int turn_led(int which, int cmd); |
| | | |
| | | int main(int argc, char *argv[]) |
| | | { |
| | |
| | | while(1) |
| | | { |
| | | turn_led(LED_R, ON); |
| | | msleep(DELAY); |
| | | turn_led(LED_R, OFF); |
| | | msleep(DELAY); |
| | | |
| | | turn_led(LED_G, ON); |
| | | msleep(DELAY); |
| | | turn_led(LED_G, OFF); |
| | | msleep(DELAY); |
| | | |
| | | turn_led(LED_B, ON); |
| | | msleep(DELAY); |
| | | turn_led(LED_B, OFF); |
| | | msleep(DELAY); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | #ifdef CONFIG_USE_WIRINGPI |
| | | #include <wiringPi.h> |
| | | |
| | | void init_led(void) |
| | | { |
| | | int i; |
| | | |
| | | wiringPiSetup(); |
| | | |
| | | for(i=0; i<LED_MAX; i++) |
| | | { |
| | | pinMode( led_gpio[i], OUTPUT ); |
| | | } |
| | | } |
| | | |
| | | int turn_led(int which, int cmd) |
| | | { |
| | | if( which<0 || which>=LED_MAX ) |
| | | return -1; |
| | | |
| | | |
| | | if( OFF == cmd ) |
| | | digitalWrite (led_gpio[which], LOW); |
| | | else |
| | | digitalWrite (led_gpio[which], HIGH); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | #else /* use libgpiod library */ |
| | | |
| | | #include <gpiod.h> |
| | | |
| | | #if 0 /* Use libgpiod lowlevel API */ |
| | | |
| | |
| | | { |
| | | gpiod_line_set_value(line, 1); |
| | | } |
| | | |
| | | msleep(DELAY); |
| | | } |
| | | |
| | | |
| | | #else /* use libgpiod ctxless high level API */ |
| | | void init_led(void) |
| | | { |
| | | |
| | | } |
| | | |
| | | void gpiod_ctxless_cb(void *data) |
| | | static void gpiod_ctxless_cb(void *data) |
| | | { |
| | | sleep(1); |
| | | } |
| | |
| | | #endif |
| | | |
| | | |
| | | #endif |
| | |
| | | CFLAGS+=-I${PWD} |
| | | #CFLAGS+=-Wall -Werror |
| | | |
| | | # default use libgpiod library |
| | | #CFLAGS+=-DCONFIG_USE_WIRINGPI |
| | | |
| | | LDFLAGS+=-lwiringPi |
| | | LDFLAGS+=-lgpiod |
| | | LDFLAGS+=-lpthread |
| | | LDFLAGS+=-lm |
New file |
| | |
| | | pi@raspberrypi:~$ gpio readall |
| | | +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+ |
| | | | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | |
| | | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ |
| | | | | | 3.3v | | | 1 || 2 | | | 5v | | | |
| | | | 2 | 8 | SDA.1 | ALT0 | 1 | 3 || 4 | | | 5v | | | |
| | | | 3 | 9 | SCL.1 | ALT0 | 1 | 5 || 6 | | | 0v | | | |
| | | | 4 | 7 | GPIO. 7 | OUT | 0 | 7 || 8 | 1 | ALT5 | TxD | 15 | 14 | |
| | | | | | 0v | | | 9 || 10 | 1 | ALT5 | RxD | 16 | 15 | |
| | | | 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 | |
| | | | 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | | |
| | | | 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 | |
| | | | | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 | |
| | | | 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | | |
| | | | 9 | 13 | MISO | IN | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 | |
| | | | 11 | 14 | SCLK | IN | 0 | 23 || 24 | 1 | IN | CE0 | 10 | 8 | |
| | | | | | 0v | | | 25 || 26 | 1 | IN | CE1 | 11 | 7 | |
| | | | 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 | |
| | | | 5 | 21 | GPIO.21 | OUT | 0 | 29 || 30 | | | 0v | | | |
| | | | 6 | 22 | GPIO.22 | OUT | 0 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 | |
| | | | 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | | |
| | | | 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 | |
| | | | 26 | 25 | GPIO.25 | OUT | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 | |
| | | | | | 0v | | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 | |
| | | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ |
| | | | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | |
| | | +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+ |
| | |
| | | #include <stdio.h> |
| | | #include <unistd.h> |
| | | #include <libgen.h> |
| | | |
| | | #include <string.h> |
| | | |
| | | #include <wiringPi.h> |
| | | #include "relay.h" |
| | | #include <gpiod.h> |
| | | |
| | | #define ON 1 |
| | | #define OFF 0 |
| | | |
| | | /* Relay #Pin(29) GPIO05(BCM 5) */ |
| | | #define relay_pin 5 |
| | | |
| | | int turn_relay(int cmd); |
| | | |
| | | int main (int argc, char **argv) |
| | | { |
| | |
| | | printf("Usage: %s [on/off]\n", basename(argv[0])); |
| | | return -1; |
| | | } |
| | | |
| | | wiringPiSetup(); |
| | | relay_init(); |
| | | |
| | | if( !strstr(argv[1], "on") || !strstr(argv[1], "on") ) |
| | | { |
| | |
| | | return 0; |
| | | } |
| | | |
| | | void relay_init(void) |
| | | static void gpiod_ctxless_cb(void *data) |
| | | { |
| | | pinMode(RELAY_PIN, OUTPUT); |
| | | sleep(3); |
| | | } |
| | | |
| | | |
| | | void turn_relay(int cmd) |
| | | int turn_relay(int cmd) |
| | | { |
| | | if( OFF == cmd ) |
| | | { |
| | | digitalWrite ( RELAY_PIN, HIGH ); |
| | | } |
| | | gpiod_ctxless_set_value("gpiochip0", relay_pin, 0, false, "relay", gpiod_ctxless_cb, NULL); |
| | | else |
| | | { |
| | | digitalWrite ( RELAY_PIN, LOW ); |
| | | } |
| | | gpiod_ctxless_set_value("gpiochip0", relay_pin, 1, false, "relay", gpiod_ctxless_cb, NULL); |
| | | } |
| | | |
| | |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2018/10/14 12:13:26" |
| | | * |
| | | * Pin connection: |
| | | * |
| | | * vcc --- #Pin17 ( 3.3v ) |
| | | * GND --- #Pin20 ( GND ) |
| | | * SDA --- #Pin02 ( SDA ) |
| | | * SCL --- #Pin03 ( SCL ) |
| | | * |
| | | * /boot/config.txt: |
| | | * |
| | | * dtparam=i2c_arm=on |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <wiringPi.h> |
| | | #include <wiringPiI2C.h> |
| | | #include <string.h> |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | |
| | | #include <errno.h> |
| | | #include <time.h> |
| | | |
| | | #include "tsl2561.h" |
| | | #include <sys/ioctl.h> |
| | | #include <linux/i2c.h> |
| | | #include <linux/i2c-dev.h> |
| | | #include <sys/types.h> |
| | | #include <sys/stat.h> |
| | | #include <fcntl.h> |
| | | |
| | | #define TSL2561_I2C_ADDR 0x39 |
| | | |
| | | #define CONTROL_REG 0x80 |
| | | #define REG_COUNT 4 |
| | | |
| | | #define POWER_UP 0x03 |
| | | #define POWER_DOWN 0x00 |
| | | |
| | | /* Register Address */ |
| | | enum |
| | | { |
| | | /* Channel_0 = DATA0HIGH<<8 + DATA0LOW */ |
| | | DATA0LOW = 0x8C, |
| | | DATA0HIGH, |
| | | |
| | | /* Channel_1 = DATA1HIGH<<8 + DATA1LOW */ |
| | | DATA1LOW, |
| | | DATA1HIGH, |
| | | }; |
| | | |
| | | |
| | | int tsl_fd = -1; |
| | | |
| | | static const int regs_addr[REG_COUNT]={DATA0LOW, DATA0HIGH, DATA1LOW, DATA1HIGH}; |
| | | |
| | | #define msleep(x) usleep( 1000*(x) ) |
| | | |
| | | int tsl2561_init(void) |
| | | { |
| | | if(tsl_fd > 0) |
| | | return 0; |
| | | |
| | | tsl_fd = wiringPiI2CSetup(TSL2561_I2C_ADDR); |
| | | if(tsl_fd < 0) |
| | | if( (tsl_fd=open("/dev/i2c-1", O_RDWR)) < 0) |
| | | { |
| | | printf("TSL2561 I2C setup failure: %s\n", strerror(errno)); |
| | | printf("TSL2561 I2C device setup failure: %s\n", strerror(errno)); |
| | | return -1; |
| | | } |
| | | else |
| | | { |
| | | |
| | | printf("TSL2561 initialise ok, tsl_fd=%d\n", tsl_fd); |
| | | } |
| | | |
| | | |
| | | return tsl_fd; |
| | | } |
| | | |
| | | #define ON 1 |
| | | #define OFF 0 |
| | | |
| | | void tsl2561_power(int cmd) |
| | | { |
| | | struct i2c_msg msg; |
| | | struct i2c_rdwr_ioctl_data data; |
| | | unsigned char buf[2]; |
| | | |
| | | msg.addr= TSL2561_I2C_ADDR; |
| | | msg.flags=0; /* write */ |
| | | msg.len= 1; |
| | | msg.buf= buf; |
| | | |
| | | data.nmsgs= 1; |
| | | data.msgs= &msg; |
| | | |
| | | msg.buf[0]=CONTROL_REG; |
| | | if( ioctl(tsl_fd, I2C_RDWR, &data) < 0 ) |
| | | { |
| | | printf("%s() ioctl failure: %s\n", __func__, strerror(errno)); |
| | | return ; |
| | | } |
| | | |
| | | |
| | | if( cmd ) |
| | | msg.buf[0]=POWER_UP; |
| | | else |
| | | msg.buf[0]=POWER_DOWN; |
| | | |
| | | if( ioctl(tsl_fd, I2C_RDWR, &data) < 0 ) |
| | | { |
| | | printf("%s() ioctl failure: %s\n", __func__, strerror(errno)); |
| | | return ; |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | |
| | | int tsl2561_readreg(unsigned char regaddr, unsigned char *regval) |
| | | { |
| | | struct i2c_msg msg; |
| | | struct i2c_rdwr_ioctl_data data; |
| | | unsigned char buf[2]; |
| | | |
| | | msg.addr= TSL2561_I2C_ADDR; |
| | | msg.flags=0; /* write */ |
| | | msg.len= 1; |
| | | msg.buf= buf; |
| | | msg.buf[0] = regaddr; |
| | | |
| | | data.nmsgs= 1; |
| | | data.msgs= &msg; |
| | | |
| | | if( ioctl(tsl_fd, I2C_RDWR, &data) < 0 ) |
| | | { |
| | | printf("%s() ioctl failure: %s\n", __func__, strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | memset(buf, 0, sizeof(buf)); |
| | | |
| | | msg.addr= TSL2561_I2C_ADDR; |
| | | msg.flags=I2C_M_RD; /* read */ |
| | | msg.len= 1; |
| | | msg.buf= buf; |
| | | |
| | | data.nmsgs= 1; |
| | | data.msgs= &msg; |
| | | |
| | | if( ioctl(tsl_fd, I2C_RDWR, &data) < 0 ) |
| | | { |
| | | printf("%s() ioctl failure: %s\n", __func__, strerror(errno)); |
| | | return -1; |
| | | } |
| | | |
| | | *regval = msg.buf[0]; |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | |
| | | int tsl2561_get_lux(void) |
| | | { |
| | | int i; |
| | | int reg_data[REG_COUNT]; |
| | | unsigned char reg_data[REG_COUNT]; |
| | | unsigned char buf; |
| | | |
| | | int chn0_data = 0; |
| | | int chn1_data = 0; |
| | | |
| | | double div = 0.0; |
| | | double lux = 0.0; |
| | | float div = 0.0; |
| | | float lux = 0.0; |
| | | |
| | | /* Power up TSL2561 */ |
| | | wiringPiI2CWrite(tsl_fd, CONTROL_REG); |
| | | wiringPiI2CWrite(tsl_fd, POWER_UP); |
| | | |
| | | delay(410); /* t(CONV) MAX 400ms */ |
| | | tsl2561_power(ON); |
| | | |
| | | msleep(410); /* t(CONV) MAX 400ms */ |
| | | |
| | | /* Read register Channel0 and channel1 data from register */ |
| | | for(i=0; i<REG_COUNT; i++) |
| | | { |
| | | wiringPiI2CWrite(tsl_fd, regs_addr[i]); |
| | | reg_data[i] = wiringPiI2CRead(tsl_fd); |
| | | //printf("write and read register: 0x%0x->%d\n", regs_addr[i], reg_data[i]); |
| | | tsl2561_readreg(regs_addr[i], ®_data[i]); |
| | | } |
| | | |
| | | chn0_data = reg_data[1]*256 + reg_data[0]; /* Channel0 = DATA0HIGH<<8 + DATA0LOW */ |
| | |
| | | |
| | | if( chn0_data<=0 || chn1_data<0 ) |
| | | { |
| | | //printf("TSL2561 get date chn0_data[%d] chn1_data[%d]\n", chn0_data, chn1_data); |
| | | lux = 0.0; |
| | | goto OUT; |
| | | } |
| | | |
| | | div = (double)chn1_data / (double)chn0_data; |
| | | div = (float)chn1_data / (float)chn0_data; |
| | | |
| | | if( div>0 && div<=0.5 ) |
| | | lux = 0.304*chn0_data-0.062*chn0_data*pow(div,1.4); |
| | |
| | | OUT: |
| | | printf("TSLl2561 get lux: %.3f\n", lux); |
| | | |
| | | wiringPiI2CWrite(tsl_fd, CONTROL_REG); |
| | | wiringPiI2CWrite(tsl_fd, POWER_DOWN); |
| | | tsl2561_power(OFF); |
| | | } |
| | | |
| | | void print_datime(void) |
| | |
| | | #!/bin/bash |
| | | |
| | | sudo apt update |
| | | # display in red |
| | | function pr_error() { |
| | | echo "" |
| | | echo -e "\033[40;31m --E-- $1 \033[0m" |
| | | echo "" |
| | | } |
| | | |
| | | sudo apt install -y make vim gawk wget curl unzip sed tree coreutils diffstat git subversion groff lzop \ |
| | | make gcc g++ libtool automake autoconf autoconf-archive flex texinfo build-essential libelf-dev bison libssl-dev |
| | | # display in yellow |
| | | function pr_warn() { |
| | | echo "" |
| | | echo -e "\033[40;33m --W-- $1 \033[0m" |
| | | echo "" |
| | | } |
| | | |
| | | # display in green |
| | | function pr_info() { |
| | | echo "" |
| | | echo -e "\033[40;32m --I-- $1 \033[0m" |
| | | echo "" |
| | | } |
| | | |
| | | function update_source() |
| | | { |
| | | APT_FILE=/etc/apt/sources.list |
| | | |
| | | pr_warn "start update apt source to ustc" |
| | | |
| | | if [ ! -f $APT_FILE.orig ] ; then |
| | | mv $APT_FILE $APT_FILE.orig |
| | | fi |
| | | |
| | | cat > $APT_FILE <<EOF |
| | | deb http://mirrors.ustc.edu.cn/raspbian/raspbian/ bullseye main contrib non-free rpi |
| | | deb-src http://mirrors.ustc.edu.cn/raspbian/raspbian/ bullseye main contrib non-free rpi |
| | | EOF |
| | | } |
| | | |
| | | function apt_update() |
| | | { |
| | | pr_warn "start update apt updata and upgrade" |
| | | |
| | | apt update |
| | | apt upgrade -y |
| | | apt autoremove -y |
| | | } |
| | | |
| | | function apt_install() |
| | | { |
| | | pr_warn "start apt install system tools" |
| | | |
| | | apt install -y make vim gawk wget curl unzip sed tree coreutils diffstat git subversion \ |
| | | groff lzop make gcc g++ libtool automake autoconf autoconf-archive flex texinfo bison \ |
| | | build-essential libelf-dev lrzsz |
| | | |
| | | # apt-cache policy libssl-dev |
| | | apt install -y libssl-dev=1.1.1n-0+deb11u1 libssl1.1 |
| | | } |
| | | |
| | | if [ `id -u` != 0 ] ; then |
| | | pr_error "This shell script must run as root." |
| | | exit 1; |
| | | fi |
| | | |
| | | update_source |
| | | |
| | | apt_update |
| | | |
| | | apt_install |
| | | |
| | | |