zoukankan      html  css  js  c++  java
  • arm linux 移植 MQTT (paho、mosquitto)

    前言

    我们在这里做2件事情:
    1)编译 paho.mqttmosquitto 2个开源项目的c版本库(mosquitto库没有用上)
    2)编译好 依赖 paho.mqtt的库编写例程 + mosquitto 服务器。

    host平台   :Ubuntu 16.04
    arm 平台 : s5p6818
    ssl : openssl-1.0.2t
    MQTT-client : paho.mqtt.c

    现在我们就来进行MQTT客户端的移植。

    MQTT服务器(Broker)在很多 云服务器中自带了,没有特殊需求是不做移植的;而且就算做了 Broker 移植,也相对简单。

    主机准备

    使用以下脚本即可。

    之前《搭建MQTT通信环境,并抓包测试》 没有介绍在:Linux下 编译运行 mosquitto 服务器,所以在下面的脚本中也有介绍,具体参考:make_mosquitto ()

    ##
    #    Copyright By Schips, All Rights Reserved
    #    https://gitee.com/schips/
    #    File Name:  make.sh
    #    Created  :  Sat 30 Nov 2019 01:56:37 PM CST
    ##
    #!/bin/sh
    BUILD_HOST=arm-linux-
    ARM_GCC=${BUILD_HOST}gcc
    ARM_CPP=${BUILD_HOST}g++
    BASE=`pwd`
    OUTPUT_PATH=${BASE}/install
    
    OPENSSL=openssl-1.0.2t
    
    make_dirs () {
        #为了方便管理,创建有关的目录
        cd ${BASE} && mkdir compressed install source -p
    }
    
    tget () { #try wget
        filename=`basename $1`
        echo "Downloading [${filename}]..."
        if [ ! -f ${filename} ];then
            wget $1
        fi
    
        echo "[OK] Downloaded [${filename}] "
    }
    
    tgit () { #try git and tar
        filename=`basename $1 | sed 's/.git//g'`
    
        echo "Clone [${filename}]..."
        if [ ! -f ${filename}.tgz ];then
            git clone $1
            rm ${filename}/.git* -rf
            echo "Making a tar file."
            tar -zcf ${filename}.tgz ${filename}
            rm ${filename} -rf
        fi
    
        echo "[OK] Cloned [${filename}] "
    }
    
    download_package () {
        cd ${BASE}/compressed
        #下载包
        tget  https://www.openssl.org/source/${OPENSSL}.tar.gz
        tgit  https://github.com/eclipse/paho.mqtt.c.git
        tgit  https://github.com/eclipse/mosquitto.git
    }
    
    tar_package () {
        cd ${BASE}/compressed
        ls * > /tmp/list.txt
        for TAR in `cat /tmp/list.txt`
        do
            tar -xf $TAR -C  ../source
        done
        rm -rf /tmp/list.txt
    }
    
    pre_make_ssl () {
        cd ${BASE}/source/${OPENSSL}
        startLine=`sed -n '/install_html_docs:/=' Makefile`
        echo $startLine
        # 为了避免 多行结果
        for startline in $startLine
        do
            lineAfter=99
            endLine=`expr $startline + 999`
            sed -i $startline','$endLine'd' Makefile
            echo "install_html_docs:" >> Makefile
            echo "	@echo skip by Schips" >> Makefile
            echo "install_docs:" >> Makefile
            echo "	@echo skip by Schips" >> Makefile
            echo "# DO NOT DELETE THIS LINE -- make depend depends on it." >> Makefile
            break
        done
    }
    
    make_ssl () {
        # 编译安装 zlib
        cd ${BASE}/source/${OPENSSL}
        rm ${OUTPUT_PATH}/${OPENSSL} -rf
        echo "SSL ABOUT"
        CC=${ARM_GCC} ./Configure no-asm shared --prefix=${OUTPUT_PATH}/${OPENSSL}
    
        sed 's/-m64//g'  -i Makefile # 删除-m64 关键字 (arm-gcc 不支持)
        #sudo mv /usr/bin/pod2man /usr/bin/pod2man_bak
        #mv doc/apps /tmp/
        pre_make_ssl
        make && make install
    }
    
    make_paho_mqtt_c () {
        cd ${BASE}/source/paho.mqtt.c
    
        make CFLAGS+="-I ${OUTPUT_PATH}/${OPENSSL}/include" 
             LDFLAGS+="-L${OUTPUT_PATH}/${OPENSSL}/lib" 
             CC=${ARM_GCC} 
             prefix=${OUTPUT_PATH}/paho.mqtt.c
    
        # BUG: make install 不符合我们的意愿
        rm ${OUTPUT_PATH}/paho.mqtt.c -rf
        mkdir ${OUTPUT_PATH}/paho.mqtt.c/lib -p
        mkdir ${OUTPUT_PATH}/paho.mqtt.c/bin -p
        mkdir ${OUTPUT_PATH}/paho.mqtt.c/include -p
    
        cp ${BASE}/source/paho.mqtt.c/build/output/lib*    ${OUTPUT_PATH}/paho.mqtt.c/lib -d -v
        cp ${BASE}/source/paho.mqtt.c/build/output/samples ${OUTPUT_PATH}/paho.mqtt.c/bin -r -v
        cp ${BASE}/source/paho.mqtt.c/build/output/test    ${OUTPUT_PATH}/paho.mqtt.c/bin -r -v
        cp ${BASE}/source/paho.mqtt.c/src/*.h       ${OUTPUT_PATH}/paho.mqtt.c/include    -v
    
    }
    
    make_mosquitto () {
        cd ${BASE}/source/mosquitto
    
        sed -r -i "/WITH_DOCS:=/ s/.*/WITH_DOCS:=no/"                       config.mk
        sed -r -i "/WITH_SRV:=/ s/.*/WITH_SRV:=no/"                         config.mk
        sed -r -i "/WITH_UUID:=/ s/.*/WITH_UUID:=no/"                       config.mk
        sed -r -i "/WITH_WEBSOCKETS:=/ s/.*/WITH_WEBSOCKETS:=no/"           config.mk
        sed -r -i "/WITH_STRIP:=/ s/.*/WITH_STRIP:=yes/"                    config.mk
        # 不添加 ssl 支持
        sed -r -i "/WITH_TLS:=/ s/.*/WITH_TLS:=no/"                         config.mk
        sed -r -i "/WITH_TLS_PSK:=/ s/.*/WITH_TLS_PSK:=no/"                 config.mk
    
        # 指定工具链
        sed -i "N;2aCC=${BUILD_HOST}gcc"                                     config.mk
        sed -i "N;2aCXX=${BUILD_HOST}g++"                                    config.mk
        sed -i "N;2aCPP=${BUILD_HOST}g++"                                    config.mk
        sed -i "N;2aCC=${BUILD_HOST}gcc"                                     config.mk
        sed -i "N;2aAR=${BUILD_HOST}ar"                                      config.mk
        sed -i "N;2aLD=${BUILD_HOST}ld"                                      config.mk
        sed -r -i "/STRIP?=/ s/.*/STRIP?=${BUILD_HOST}strip/"     config.mk
        # 设置输出路径
        echo "DESTDIR=${OUTPUT_PATH}/mosquitto"                 >>  config.mk
        echo "prefix=\" >>  config.mk
    
        make  && make install
    
        # 添加 ssl 支持 下编译的 mosquitto
       #sed -r -i "/WITH_TLS:=/ s/.*/WITH_TLS:=yes/"                        config.mk
       #sed -r -i "/WITH_TLS_PSK:=/ s/.*/WITH_TLS_PSK:=yes/"                config.mk
       #make 
       #    CFLAGS+="-I ${OUTPUT_PATH}/${OPENSSL}/include" 
       #    LDFLAGS+="-L${OUTPUT_PATH}/${OPENSSL}/lib -lssl -lcrypto"
    
       #make 
       #    CFLAGS+="-I ${OUTPUT_PATH}/${OPENSSL}/include" 
       #    LDFLAGS+="-L${OUTPUT_PATH}/${OPENSSL}/lib -lssl -lcrypto" 
       #    install
    }
    
    make_dirs
    download_package
    tar_package
    make_ssl
    make_paho_mqtt_c
    make_mosquitto
    exit $?
    
    

    目标板准备

    将install 下运行库拷贝到板子上,添加到路径即可。

    测试

    使用以下的测试程序,服务器根据自己的需求进行指定

    有关的例程在 ${paho_mqtt_c}/src/samples 可以找到。

    /*
    #    Copyright By Schips, All Rights Reserved
    #    https://gitee.com/schips/
    #
    #    File Name:  main.cpp
    #    Created  :  Sun 09 Feb 2020 10:14:44 AM CST
    */
    
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <MQTTClient.h>   /* MQTT头文件的位置  */
    #include <sys/time.h>
    #include <termios.h>
    
    
    #define ADDRESS     "tcp://localhost:1883"   /* 指定服务器的ip地址 这里使用本机的 mosquitto 进行测试使用  */
    #define CLIENTID    "ExampleClientPub"
    #define TOPIC       "MQTT Examples"
    #define PAYLOAD     "Hello World!"
    #define QOS         1
    #define TIMEOUT     10000L
    
    using namespace std;
    int main(int argc, char* argv[])
    {
        MQTTClient client;
        MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
        MQTTClient_message pubmsg = MQTTClient_message_initializer;
        MQTTClient_deliveryToken token;
    
        MQTTClient_message *receivemsg = NULL ;
        char* topicName_rev = NULL;
        int   topicLen_rev;
    
        int rc;
        int i;
    
        MQTTClient_create(&client, ADDRESS, CLIENTID,
        MQTTCLIENT_PERSISTENCE_NONE, NULL);
        conn_opts.keepAliveInterval = 60;
        conn_opts.cleansession = 1;
    
        if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
        {
            printf("Failed to connect, return code %d
    ", rc);
            exit(-1);
        }
        pubmsg.payload = (void *)PAYLOAD;
        pubmsg.payloadlen = strlen(PAYLOAD);
        pubmsg.qos = QOS;
        pubmsg.retained = 0;
        MQTTClient_subscribe(client, "test", 1);                        /* 订阅一个客户端 的一个话题*/
        usleep(10000);
        MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token); /* 发送消息 */
        printf("Waiting for up to %d seconds for publication of %s
    "
                "on topic %s for client with ClientID: %s
    ",
                (int)(TIMEOUT/1000), PAYLOAD, TOPIC, CLIENTID);
        rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
        printf("Message with delivery token %d delivered
    ", token);
        for(;;)
        {
                   if(MQTTClient_isConnected(client) == true)   /* 检测连接状态 */
                   {
                       printf("alive 
    ");
                   }else{
                       printf(" no alive 
    ");
                       break;
                   }
                rc = MQTTClient_receive(client,&topicName_rev, &topicLen_rev, &receivemsg,5000); /* 接收消息 */
                   if(rc == MQTTCLIENT_SUCCESS)
                   {
                    printf("Message REv  %d delivered
    ", rc);
                    printf("topicName: %s  topicName_LEN: %d 
    ", topicName_rev,topicLen_rev);
                    if(topicName_rev != NULL)                          /* 滤掉心跳包 */
                    {
                        printf("topicName: ");
                        for(i=0;i<topicLen_rev;i++)
                        {
                            printf(" %c ", topicName_rev[i]);
                        }
                        printf("
    ");
                        printf("Data: %s  len:%d msgid: %d 
    ",(char *)receivemsg->payload,receivemsg->payloadlen,receivemsg->msgid);
                         if(strcmp((char *)receivemsg->payload,"ESC") == 0)
                        {
                            printf("ESC 
    ");
                            break;
                        }
                    }
                }
    
                usleep(10000);
                usleep(100000);
        }
        MQTTClient_disconnect(client, 10000);
        MQTTClient_destroy(&client);
        return rc;
    }
    
    

    编译命令

    arm-linux-g++ -I ./paho.mqtt.c/src -L ./paho.mqtt.c/build/output/ -lpaho-mqtt3c main.cpp  -o client
    
  • 相关阅读:
    用java实现的微信公众号爬虫
    装饰模式
    输入一个数,查询该数是否为素数
    Machine-learning-DecisionTree
    Circles of Waiting
    GRE阅读
    云数据库POLARDB产品解读之二:如何做到高性价比
    奉上一份云上数据安全保护指南
    从双十一看阿里云安全的“创世纪”——采访阿里云安全掌门人肖力有感
    阿里云移动研发平台EMAS,是如何连续5年安全护航双11的?
  • 原文地址:https://www.cnblogs.com/schips/p/12275173.html
Copyright © 2011-2022 走看看