温度上报到阿里云物联网平台


前言

在上篇文章中我们用MQTT.fx模拟客户端实现了与阿里云物联网平台的双向通信,接下来我们自己动手编程使用mosquitto库实现一个客户端来实现一个发布端。

一、iniparser 和 json

1、为什么要使用iniparser库

iniparser简介:https://blog.csdn.net/qq_47548559/article/details/120920002

与阿里云进行通信时,我们需要如下一些信息,例如在使用MQTT.fx时:
在这里插入图片描述
复制保存一下,另外之前发布和订阅的topic也要记下来:
在这里插入图片描述
这些都是我们在项目中要用到的配置信息,具体应用在:
clientid:struct mosquitto *mosquitto_new( const char * id, bool clean_session, void * obj )
brokeraddress and brokerport:int mosquitto_connect( struct mosquitto * mosq, const char * host, int port, int keepalive )
username and password:int mosquitto_username_pw_set(struct mosquitto * mosq, const char *username, const char *password )
topic:int mosquitto_publish( struct mosquitto * mosq, int * mid, const char * topic, int payloadlen, const void * payload, int qos, bool retain )
我们当然可以直接写死在代码里,但是这样一来,代码复用性不高,换一个设备那么就要改一次源码来更改设备配置信息。
所以我们写一个.ini文件,这样当我们更换设备的时候只需要修改这个.ini文件中的信息即可。然后在代码中使用iniparser库中API。

2.为什么要使用json

JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
打个比方:如果我们发布的消息为:在这里插入图片描述
那么在阿里云上:

在这里插入图片描述
payload must be json format 负载(消息)必须为json格式。
所以我们这样写:
在这里插入图片描述
再看一下阿里云:
在这里插入图片描述
这下就成功啦!

因为我们是使用的阿里云提供的标准物模型,所以我们的消息格式应该遵循阿里云的规范。这就是我们要使用json的原因。
其中:param 代表参数。参数有两个 一个 data 一个 CurrentTemperature (这两个参数就是我们之前定义功能中的标识符),你可以这样理解,阿里云可以接收到以json格式发送的任何消息,例如:
在这里插入图片描述
阿里云上
在这里插入图片描述
同一时间内显示 ture 和 false 你可以这样理解 接收到了,但是参数不匹配 无法解析,(tsl parse failed),我在网上搜不到tsl 相关知识,但是在这里我们可以粗略的认为,阿里云收到了消息,但是因为参数不匹配,无法对消息进行解析,也就无法获取到温度和测试消息(如有错误请指正)。详细请 参考:https://developer.aliyun.com/article/777052
为了验证我的猜测:我又测试了正常情况:
在这里插入图片描述

在这里插入图片描述
好了到这里我们应该清楚为什么要学习json了。json的学习参考这篇博客:
https://blog.csdn.net/qq_47548559/article/details/120922787

二、编程实现客户端

1、大致流程

在这里插入图片描述

2.配置信息处理

/********************************************************************************
 *      Copyright:  (C) 2021 lastbreath<2631336290@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  configoperate.h
 *    Description:  This head file 
 *
 *        Version:  1.0.0(10/18/2021)
 *         Author:  lastbreath <2631336290@qq.com>
 *      ChangeLog:  1, Release initial version on "10/18/2021 06:12:09 PM"
 *                 
 ********************************************************************************/

#ifndef CONFIGOPERATE_H
#define CONFIGOPERATE_H


#define SIZE    256

#define DEFAULT_CLIENTID    "12345|securemode=3,signmethod=hmacsha1|"
#define DEFAULT_USERNAME    "test&ghcey1O2Yxm"
#define DEFAULT_PASSWORD "D090FBDCC327200DAD3083684A891A1C7992FACB"
#define DEFAULT_BROKER_ADDRESS    "ghcey1O2Yxm.iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define DEFAULT_BROKER_PORT 1883
#define DEFAULT_SUB_TOPIC   "/sys/ghcey1O2Yxm/test/thing/service/property/set"

#define DEFAULT_PUB_TOPIC   "/sys/ghcey1O2Yxm/test/thing/event/property/post"


#define DEFAULT_METHOD  "thing.event.property.post"
#define DEFAULT_JSONID  "0801"
#define DEFAULT_IDENTIFIER  "data"
#define DEFAULT_VERSION "1.0.0"


#define KEEP_ALIVE  60

enum mode
{
    SUB,
    PUB
};
typedef struct mqtt_user_data{

    char    clientid[SIZE];
    char    username[SIZE];
    char    password[SIZE];
    char    brokeraddress[SIZE];
    int     brokerport;
    char    topic[SIZE];
    
    char    method[SIZE];
    char    jsonid[SIZE];
    char    identifier[SIZE];
    char    version[SIZE];
             
}mqtt_user_data;


int set_config(char *ini,char *host,int port, char *clientid,char *uname,char *pwd,char *topic);
int get_config(char *path,mqtt_user_data *mqtt,int mode);


#endif

3.主要流程

/*********************************************************************************
 *      Copyright:  (C) 2021 lastbreath<2631336290@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  clien.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(08/08/2021)
 *         Author:
 *
 *         lastbreath <2631336290@qq.com>
 *      ChangeLog:  1, Reliease initial version on "21/10/2021 16:08:41 PM"
 *                 
 ********************************************************************************/


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/resource.h>
#include <netdb.h>
#include <signal.h>
#include <libgen.h>

#include "mosquitto.h"
#include "ds18b20.h"
#include "cJSON.h"
#include "iniparser.h"
#include "configoperate.h"


#define INI_PATH "./mqtt_aliyun_conf.ini"
#define KEEP_ALIVE 60




int g_stop = 0;

static inline void print_usage(char *progname);//内联函数,空间换时间。编译时期展开。

void sig_handler(int sig_num)
{
    if(sig_num == SIGUSR1)
        g_stop = 1;

}

void connect_callback(struct mosquitto *mosq,void *obj,int rc);


int main (int argc, char **argv)
{

    char        *progname = basename(argv[0]);
    
    
    int                         brokerport = 0;
    char                        *brokeraddress = NULL;
    char                        *clientid = NULL;
    char                        *username = NULL;
    char                        *password = NULL;


    char                        *topic = NULL;
    struct mosquitto            *mosq = NULL;
    int                         daemon_run = 0;
    int                         opt = -1;
    int                         rv;
    char                        buffer[BUF_SIZE];
    int                         log_fd;
    
    struct mqtt_user_data       mqtt;


     struct option options[] = 
     {
         {"daemon",no_argument,NULL,'d'},
         {"topic", required_argument,NULL,'t'},
         {"brokeraddress", required_argument,NULL,'H'},
         {"clientid", required_argument, NULL, 'i'},
         {"brokerport",required_argument,NULL,'p'},
         {"help",no_argument,NULL,'h'},
         {"username",required_argument,NULL,'u'},
         {"password",required_argument,NULL,'P'},
         {NULL,0,NULL,0}
     };



     while((opt = getopt_long(argc,argv,"dhp:t:i:u:P:H:",options,NULL)) != -1)
     {
        
         switch(opt)
         
         {

             case 't':
                 topic = optarg;
                 break;

             case 'i':
                 clientid = optarg;
                 break;

             case 'H':
                 brokeraddress = optarg;
                 break;
             case 'u':
                 username = optarg;
                 break;
            case 'P':
                 password = optarg;
                 break;

             case 'd':
                 daemon_run = 1;
                 break;
             case 'p':
                 brokerport = atoi(optarg);
                 break;
             case 'h':
                 print_usage(argv[0]);
                 return 0;
             default:
                 break;
         }
     }

    
     //set_config(INI_PATH,brokeraddress,brokerport,clientid,username,password,topic);
    

     if(daemon_run)
     {
         printf("program %s running in backgrund\n", progname);
         if( (log_fd = open("client.log", O_CREAT|O_RDWR, 0666)) < 0)
         {
             printf("open() failed:%s\n", strerror(errno)) ;
             return -2;
         }

        dup2(log_fd, STDOUT_FILENO) ;
        dup2(log_fd, STDERR_FILENO) ;

         daemon(1,1);
     }
     
    
     signal(SIGUSR1,sig_handler);


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


     rv = get_config(INI_PATH,&mqtt,PUB);



     mosquitto_lib_init();
     mosq = mosquitto_new(mqtt.clientid,true,(void *)&mqtt);
     if(!mosq)
     {
         printf("mosquitto_new() failed: %s\n",strerror(errno));
         mosquitto_lib_cleanup();
         return -1;
     }


     if(mosquitto_username_pw_set(mosq,mqtt.username,mqtt.password) != MOSQ_ERR_SUCCESS)
     {
         printf("mosquitto_username_pw_set failed: %s\n",strerror(errno));
         /*mosquitto_destroy(mosq);
         mosquitto_lib_cleanup();
         return -1;*/
         goto   cleanup;
     }
     printf("Create mosquitto successfully!\n");
    
     mosquitto_connect_callback_set(mosq,connect_callback);

     /*if(mosquitto_loop_start(mosq) != MOSQ_ERR_SUCCESS)
     {

                printf("mosquitto_loop_start() failed: %s\n",strerror(errno));
                //mosquitto_destroy(mosq);
                //mosquitto_lib_cleanup();
                //return -1;
                goto cleanup;
     }
    
     printf("mosquitto_loop_start() successfully!\n");*/
        
     //printf("%s\n",brokeraddress);
     //printf("%d\n",brokerport);
     while(!g_stop)
     {
         printf("into while:\n");
        if(mosquitto_connect(mosq, mqtt.brokeraddress,mqtt.brokerport,KEEP_ALIVE) != MOSQ_ERR_SUCCESS)
        {
            printf("mosquitto_connect() failed: %s\n",strerror(errno));
            //continue;
            goto cleanup;
            
        }
        printf("connect successfully\n");
        mosquitto_loop_forever(mosq,-1,1);
        sleep(30);
     }

cleanup:
    close(log_fd);
    mosquitto_destroy(mosq);
    mosquitto_lib_cleanup();
     return 0;
} 

void print_usage(char *progname)
{
    printf("%s usage:\n",progname);
    printf("Example: %s -h ${brokeraddress} -p ${brokerport} -i ${clientid} -u ${username} -p ${password} -t${topic} -h ${help} -d ${daemon}\n",progname);
    printf("-h(--host): sepcify brokeraddress.\n");
    printf("-p(--port): sepcify brokerport.\n");
    printf("-h(--Help): print this help information.\n");
    printf("-d(--daemon): set program running on background.\n");
    printf("-i(--clientid): sepcify the clientid.\n");
    printf("-u(--username): sepcify username of the client.\n");
    printf("-p(--password): sepcify password of the username.\n");
    printf("-t(--topic): sepcify topic of the client.\n");
    printf("-d(--daemon): running in backgrund.\n");
}

void connect_callback(struct mosquitto *mosq,void *obj,int rc)
{
    printf("get into connect_callback():\n");
    
    float t = 27.000000;

    if(ds18b20_get_temperature(&t) < 0)
    {
        printf("ds18b20_get_temperature failed.\n");
        return;
    }


    cJSON   *root = cJSON_CreateObject();
    cJSON   *item = cJSON_CreateObject();


    if(!obj)
    {
        printf("invalid_argument in %s\n",__FUNCTION__);
        return;
    }

    struct mqtt_user_data *mqtt = (mqtt_user_data *)obj;

    cJSON_AddItemToObject(root,"method",cJSON_CreateString(mqtt->method));
    cJSON_AddItemToObject(root,"id",cJSON_CreateString(mqtt->jsonid));
    cJSON_AddItemToObject(root,"params",item);
    cJSON_AddItemToObject(item,"CurrentTemperature",cJSON_CreateNumber(t));
    cJSON_AddItemToObject(root,"version",cJSON_CreateString(mqtt->version));
    char *msg = cJSON_Print(root);
    printf("%s\n",msg);


    if(!rc)
    {
        if(mosquitto_publish(mosq,NULL,mqtt->topic,strlen(msg),msg,0,NULL) != MOSQ_ERR_SUCCESS)
        {
            printf("mosquitto_publish failed: %s\n",strerror(errno));
            return;
        }
    }

    mosquitto_disconnect(mosq);

}


4.运行结果

在这里插入图片描述
在这里插入图片描述
打开阿里云可以看到温度在实时更新啦。
项目源码地址:https://gitee.com/lastbreath/apue/tree/master/

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值