利用mosquitto库实现客户端上报云平台

这里做的是上报阿里云平台

首先需要连接阿里云测试

这里我也是参考别人博客一步步做的...所以还是直接贴出链接:

https://blog.csdn.net/qq997758497/article/details/90757307

按照上面博客成功用MQTT.fx订阅与发布之后,接下来看一下我们得到的东西

利用mosquitto库实现客户端上报云平台_第1张图片

订阅和发布的主题,这里用/sys/a1R4lbARNLO/${deviceName}/thing/event/property/post发布主题还有/sys/a1R4lbARNLO/${deviceName}/thing/service/property/set订阅主题这两个来测试,当然也可以用其他的主题

利用mosquitto库实现客户端上报云平台_第2张图片

比起刚刚的产品主题Topic类,功能更像是主题

利用mosquitto库实现客户端上报云平台_第3张图片

使用在线调试,发布消息MQTT.fx接收到的消息以Json格式打印出来

利用mosquitto库实现客户端上报云平台_第4张图片

 

阿里云的上报会比较严格,还需要用相同的Json格式发布阿里云平台才能收得到,将订阅收到的Json格式消息复制到发布端去发布。

利用mosquitto库实现客户端上报云平台_第5张图片

 

最少也需要以如下格式:

{

  "params" : {

    "Data" : "Test"

  },

}

阿里云平台才接收数据显示对应功能的数据

有了这些东西之后就可以使用mosquitto连接阿里云平台了,用mosquitto_sub订阅。

利用mosquitto库实现客户端上报云平台_第6张图片

 用mosquitto_pub发布的时候载荷不符合Json格式,上报的数据对应的功能处并没有收到,可能是我还没完全掌握mosquitto_pub的用法吧

 

 

接下来就用mosquitto库自己实现mqtt客户端

使用了开源的iniparser库来操作配置文件,对于这些需要很多参数的程序,用一个配置文件来解决就很方便,可以了解一下iniparser库:

https://wenku.baidu.com/view/fba7c147c4da50e2524de518964bcf84b8d52d1a.html

一开始需要修改配置文件,配置文件默认上报到我的阿里云平台

利用mosquitto库实现客户端上报云平台_第7张图片

订阅需要修改host,阿里云平台设备的username,passwd,客户端ID client_id,修改[sub_topic]topic来订阅主题,阿里云是通过json格式订阅和发布不同功能的mqtt报文,修改[ali_json]identifier标识符id等。

获取连接配置:

int gain_mqtt_conf(char *ini_path,st_mqtt *mqtt, int type)

{

    dictionary          *ini = NULL;

    const char          *hostname ;

    int                 port ;

    const char          *username ;

    const char          *passwd ;

    const char          *clientid ;

    const char          *topic ;

    const char          *method ;

    const char          *json_id ;

    const char          *identifier ;

    const char          *version ;



    if(!ini_path || !mqtt)

    {

        printf("invail input parameter in %s\n", __FUNCTION__) ;

        return -1 ;

    }

    ini = iniparser_load(ini_path); //Load ini file get mqtt conf

    if ( ini == NULL ) {

        printf("iniparser_load error!\n");

        return -2;

    }

    hostname = iniparser_getstring(ini, "mqtt_server_addr:host", DEFAULT_HOSTNAME);

    port = iniparser_getint(ini, "mqtt_server_addr:port", DEFAULT_PORT);

    username = iniparser_getstring(ini, "user_passwd:username", DEFAULT_USERNAME);

    passwd = iniparser_getstring(ini, "user_passwd:passwd", DEFAULT_PASSWD);

    clientid = iniparser_getstring(ini, "client_id:id", DEFAULT_CLIENTID);

    identifier = iniparser_getstring(ini,"json:identifier", DEFAULT_IDENTIFIER) ;

    if(type == TYPE_SUB)

        topic = iniparser_getstring(ini, "sub_topic:topic", DEFAULT_SUBTOPIC) ;

    else if(type == TYPE_PUB)

    {

        topic = iniparser_getstring(ini,"pub_topic:topic", DEFAULT_PUBTOPIC) ;

        method = iniparser_getstring(ini,"json:method", DEFAULT_METHOD) ;

        json_id = iniparser_getstring(ini,"json:id", DEFAULT_JSONID) ;

        version = iniparser_getstring(ini,"json:version", DEFAULT_VERSION) ;



    }

    strncpy(mqtt->hostname, hostname,BUF_SIZE) ;

    mqtt->port = port ;



    strncpy(mqtt->username, username,BUF_SIZE) ;

    strncpy(mqtt->passwd, passwd,BUF_SIZE) ;

    strncpy(mqtt->clientid, clientid,BUF_SIZE) ;

strncpy(mqtt->topic, topic,BUF_SIZE) ;

    strncpy(mqtt->identifier, identifier,BUF_SIZE) ;

    if(type == TYPE_PUB)

    {

        strncpy(mqtt->method, method,BUF_SIZE) ;

        strncpy(mqtt->json_id, json_id,BUF_SIZE) ;

        strncpy(mqtt->version, version,BUF_SIZE) ;

    }



#if 0

    printf(" MQTT hostname[%s]:%d,\n clientid:%s,\n username:%s, passwd:%s,\n topic:%s\n",

            mqtt->hostname, mqtt->port, mqtt->clientid, mqtt->username, mqtt->passwd, mqtt->topic);

#endif

    iniparser_freedict(ini); //Relaese ini file

    return 0 ;

}

一开始没改配置文件的话,可以通过传入参数去修改如果没有传入参数默认用配置文件中的配置:

 

利用mosquitto库实现客户端上报云平台_第8张图片

可通过选项传参修改配置文件中的配置host,port,username,passwd,client_id,topic 这些参数

设置mqtt连接需要的参数:

void set_mqtt_conf(char *ini_path,char *host,int port,char *id,char *user,char *passwd,char *topic)

{

    char    _mqtt_port[16] ;

    char    *mqtt_port ;



    if(port)

    {

        snprintf(_mqtt_port, sizeof(_mqtt_port), "%d", port) ;

        mqtt_port = _mqtt_port ;

    }

    else{

        mqtt_port = NULL ;

    }

    set_conf(ini_path,host,"mqtt_server_addr:host") ;

    set_conf(ini_path,mqtt_port,"mqtt_server_addr:port") ;

    set_conf(ini_path,id,"client_id:id") ;

    set_conf(ini_path,user,"user_passwd:username") ;

    set_conf(ini_path,passwd,"username:passwd") ;



    set_conf(ini_path,topic,"sub_topic:topic") ;

    set_conf(ini_path,topic,"pub_topic:topic") ;



}

设置到配置文件里面

void set_conf(char *ini_path, char *value, const char * entry)

{

    int                 rv = 0;

    dictionary          *ini = NULL;

    FILE                *fp;

    

    if(!ini_path || !value || !entry)

    {

        return ;

    }

    printf("Ini file%s,set entry %s value=%s\n",ini_path, entry, value) ;


    ini = iniparser_load(ini_path); //Load ini file get mqtt conf

    if ( ini == NULL ) {

        printf("iniparser_load error!\n");

        return ;

    }



    if(iniparser_find_entry(ini,entry)){

        printf("the value is: %s\r\n", iniparser_getstring(ini, entry, ""));

    }else{

        printf("the entry not exist...\r\n");

        return ;

    }



    rv = iniparser_set(ini, entry,value) ;

    if(rv != 0)

    {

        printf("iniparser_set %s=%s error\n",entry,value ) ;

        goto cleanup ;

    }

    fp = fopen(ini_path, "w");

    iniparser_dump_ini(ini, fp);

    fclose(fp);


cleanup:

    iniparser_freedict(ini); //Relaese ini file

}

mosq_sub的主函数

int main(int argc, char **argv)

{

    int                 rv = -1 ;

    st_mqtt             mqtt ;

    struct mosquitto    *mosq = NULL;

    bool                session = true ;

    st_mosq_ctx         mosq_ctx ;

    int                 opt = -1 ;

    int                 daemon_run = 0 ;

    char                *program_name ;

    char                *host=NULL ;

    int                 port = 0 ;

    char                *id = NULL ;

    char                *user = NULL ;

    char                *passwd = NULL ;

    char                *topic = NULL ;

    

    program_name = basename(argv[0]) ;



    const char *short_opts = "i:h:p:P:u:t:dH";                    

    const struct option long_opts[] =   {  

        {"host", required_argument, NULL, 'h'},    

        {"daemon", no_argument, NULL, 'd'},  

        {"help", no_argument, NULL, 'H'},  

        {"port", required_argument, NULL, 'p'},  

        {"id", required_argument, NULL, 'i'},  

        {"passwd", required_argument, NULL, 'P'},  

        {"user", required_argument, NULL, 'u'},  

        {"topic", required_argument, NULL, 't'},  

        {0, 0, 0, 0}

    };  

    while ((opt= getopt_long(argc, argv, short_opts, long_opts,NULL)) != -1)

    {

        switch (opt)

        {

            case 'i':

                id = optarg ;

                break ;

            case 'P':

                passwd = optarg ;

                break ;

            case 'u':

                user = optarg ;

                break ;

            case 'p':

                port = atoi(optarg) ;

                break ;

            case 'd':

                daemon_run = 1 ;

                break ;

            case 'h':

                host = optarg ;

                break ;

            case 't':

                topic  = optarg ;

                break ;

            case 'H':

                print_usage(program_name) ;

                return 0 ;

        }

    }

    set_mqtt_conf(INI_PATH,host, port, id, user, passwd, topic) ;


    memset(&mosq_ctx,0,sizeof(mosq_ctx)) ;

    memset(&mqtt,0,sizeof(mqtt)) ;


    rv = gain_mqtt_conf(INI_PATH,&mqtt,TYPE_PUB) ;

    if(rv < 0)

    {

        printf("gain mqtt conf error\n") ;

        return -1 ;

    }

    strncpy( mosq_ctx.topic, mqtt.topic, sizeof(mosq_ctx.topic)) ;

    strncpy( mosq_ctx.identifier, mqtt.identifier, sizeof(mosq_ctx.identifier)) ;



    /*  Program running in backgrund    */

    if(daemon_run)

    {

        daemon(1,1) ;

    }



    /*   必须在任何其他mosquitto功能之前调用。 */

    mosquitto_lib_init() ;


    /*   创建一个新的mosquitto客户端实例 */

    mosq = mosquitto_new(mqtt.clientid, session, (void*)&mosq_ctx) ;

    if(!mosq)

    {

        printf("Mosquitto_new() failed: %s\n", strerror(errno)) ;

        goto cleanup ;

    }

    printf("Create mosquitto sucessfully!\n");


    /*      Set callback function    */

    mosquitto_connect_callback_set(mosq, conn_callback) ;

    mosquitto_message_callback_set(mosq, message_callback);


    /*   配置mosquitton实例的用户名和密码    */

    if( mosquitto_username_pw_set(mosq, mqtt.username, mqtt.passwd) != MOSQ_ERR_SUCCESS )

    {

        printf("Mosq_usee_pw_set() failed: %s\n", strerror(errno) );

        goto cleanup ;

    }



    if( mosquitto_connect(mosq, mqtt.hostname, mqtt.port, KEEP_ALIVE) )

    {

        printf("connect mqtt server failed\n") ;

        goto cleanup ;

    }

    mosquitto_loop_forever(mosq, -1, 1);


cleanup:

    printf("program will exit\n");

    mosquitto_destroy(mosq) ;

    mosquitto_lib_cleanup() ;



    return 0 ;

}

登录阿里云平台进行测试

利用mosquitto库实现客户端上报云平台_第9张图片

 

我这里发布的是Data功能,使用阿里云平台的在线调试发布消息 客户端收到消息

利用mosquitto库实现客户端上报云平台_第10张图片

 

使用参数进行连接订阅

利用mosquitto库实现客户端上报云平台_第11张图片

 客户端收到的消息

利用mosquitto库实现客户端上报云平台_第12张图片

 

下面一行打印的是通过配置里的[ali_json]:identifier = Data,标识符去找该标识符对应的值,也就是阿里云平台对应的功能。

发布端代码也大致如此就不再说了,还有存在BUG,如传参的时候设置用户名buntu&a1R4lbARNLO时遇到&后面的就报错a1R4lbARNLO:未找到命令,暂时还没解决,还有发布端一开始想着是可能会上报一些温度或者是某些需要用到硬件的获取的值,然后运行进行发布,载荷传参以及配置文件里都还没有....

在客户端mosq_pub.c代码中,可修改发布的内容和间隔时间 10秒钟发布一次

利用mosquitto库实现客户端上报云平台_第13张图片

 

在回调函数里修改发布内容

利用mosquitto库实现客户端上报云平台_第14张图片

发布主题可以通过传参或者修改配置文件修改,发布对应功能的标识还是得从配置文件中去改

利用mosquitto库实现客户端上报云平台_第15张图片

 

最后就是测试,客户端发布

利用mosquitto库实现客户端上报云平台_第16张图片

 

阿里云平台查看对应的消息

利用mosquitto库实现客户端上报云平台_第17张图片

还是有很多不完善的地方有空好好学习再慢慢修改

源码:https://gitee.com/wyj98/Demo_mqttclient

你可能感兴趣的:(linux学习)