【MQTT】通过mosquitto库连接阿里云远程上报温度

本文详细介绍了如何在物联网设备上使用Mosquitto库连接阿里云,包括下载、编译安装、配置连接参数、初始化、账号管理以及数据发布等关键步骤。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、创建阿里云产品

二、下载mosquitto库

1.下载源码

2.解压源码

3.进入源码目录,编译下载安装

三、连接阿里云

1.MQTT初始化

2.MQTT清除

3.新建客户端

4.释放客户端

5.设置账号密码

6.确认连接回调函数

7.连接MQTT代理/服务器

8.网络事件循环处理

9.发布主题

10.断开MQTT代理/服务器

主函数代码如下

总结


前言

        Mosquitto库是一个开源的消息代理项目,用于实现MQTT(Message Queuing Telemetry Transport)协议。MQTT是一种轻量级的通信协议,适用于低带宽、高延迟或不稳定网络环境下的物联网设备通信。Mosquitto库提供了MQTT协议的服务器和客户端实现,可以用于构建物联网应用和设备之间的通信。Mosquitto库支持多种平台和编程语言,并提供了丰富的功能和灵活的配置选项。


一、创建阿里云产品

如何创建产品的详细过程可查看我上篇文章介绍,链接如下:

http://t.csdnimg.cn/M61SI

二、下载mosquitto库

1.下载源码

wget http://mosquitto.org/files/source/mosquitto-1.6.10.tar.gz

2.解压源码

tar -zxvf mosquitto-1.6.10.tar.gz

3.进入源码目录,编译下载安装

cd mosquitto-1.6.10/
make
sudo make install

三、连接阿里云

主要用到的API如下:

1.MQTT初始化

int mosquitto_lib_init(void)
功能:
使用mosquitto库函数前,要先初始化,使用之后就要清除。清除函数;int mosquitto_lib_cleanup()
返回值:MOSQ_ERR_SUCCESS

2.MQTT清除

int mosquitto_lib_cleanup(void)
功能:
使用MQTT之后,清除工作
返回值MOSQ_ERR_SUCCESS

3.新建客户端

struct mosquitto *mosquitto_new(const char * id, bool clean_session, void * obj)
参数
id:如果为NULL,将生成一个随机客户端ID。如果id为NULL,clean_session必须为true。
clean_session:设置为true以指示代理在断开连接时清除所有消息和订阅,设置为false以指示其保留它们,客户端将永远不会在断开连接时丢弃自己的传出消息就是断开后是否保留订阅信息true/false
obj:用户指针,将作为参数传递给指定的任何回调
返回
成功时返回结构mosquitto的指针,失败时返回NULL,询问errno以确定失败的原因:ENOMEM内存不足。EINVAL输入参数无效。 

4.释放客户端

void mosquitto_destroy(struct mosquitto * mosq)
功能
释放客户端
参数:mosq: struct mosquitto指针

5.设置账号密码

int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username,  const char *passworp)
参数
     struct mosquitto *mosq :客户端
     const char *username : 以字符串形式发送的用户名,或以NULL形式关闭认证。
     const char *passworp:以字符串形式发送的密码。 当用户名有效时,设置为NULL,以便只发送一个用户名。
返回值
    成功时返回MOSQ_ERR_SUCCESS。
    如果输入参数无效,返回MOSQ_ERR_INVAL。
    如果发生内存不足的情况,返回MOSQ_ERR_NOMEM。

6.确认连接回调函数

void mosquitto_connect_callback_set(struct mosquitto * mosq, void (*on_connect)(struct mosquitto *mosq, void *obj, int rc) )
功能:连接确认回调函数,当代理发送CONNACK消息以响应连接时,将调用此方法。
参数:
    struct mosquitto * mosq:客户端通配符
    void (*on_connect):回调函数
    struct mosquitto *mosq:客户端数据
    void *obj:创建客户端的回调参数(mosquitto_new中提供的用户数据)
    int rc: 
        0-成功
        1-连接被拒绝(协议版本不可接受)
        2-连接被拒绝(标识符被拒绝)
        3-连接被拒绝(经纪人不可用)
        4-255-保留供将来使用

7.连接MQTT代理/服务器

int mosquitto_connect(struct mosquitto * mosq, const char * host, int port, int keepalive)
功能: 连接到MQTT代理/服务器(主题订阅要在连接服务器之后进行)
参数:
    struct mosquitto * mosq:客户端
    const char * host:服务器ip
    int port:服务器端口号
    int keepalive:保持连接的时间间隔, 单位秒 
返回:
    MOSQ_ERR_SUCCESS 成功。
    MOSQ_ERR_INVAL 如果输入参数无效。
    MOSQ_ERR_ERRNO 如果系统调用返回错误。变量errno包含错误代码

8.网络事件循环处理

int mosquitto_loop_start(struct mosquitto * mosq)
功能:网络事件循环处理函数,通过创建新的线程不断调用mosquitto_loop() 函数处理网络事件,不阻塞
参数:
    struct mosquitto * mosq:客户端
返回:
    MOSQ_ERR_SUCCESS 成功。
    MOSQ_ERR_INVAL 如果输入参数无效。
    MOSQ_ERR_NOT_SUPPORTED 如果没有线程支持。

9.发布主题

int mosquitto_publish(struct mosquitto * mosq, int * mid, const char * topic, int payloadlen, const void * payload, int qos, bool retain)
功能:主题发布的函数
参数:
    struct mosquitto * mosq:客户端
    int * mid:指向int的指针。如果不为NULL,则函数会将其设置为该特定消息的消息ID
    const char * topic:要发布的主题,以'\0'结尾的字符串
    int payloadlen:主题消息的内容长度
    const void * payload:主题消息的内容,指向要发送的数据的指针,如果payloadlen >0,则它必须时有效的存储位置
    int qos:整数值0、1、2指示要用于消息的服务质量
    bool retain:设置为true以保留消息
返回:
    MOSQ_ERR_SUCCESS 成功。
    MOSQ_ERR_INVAL 如果输入参数无效。
    MOSQ_ERR_NOMEM 如果发生内存不足的情况。
    MOSQ_ERR_NO_CONN 如果客户端未连接到代理。
    MOSQ_ERR_PROTOCOL 与代理进行通信时是否存在协议错误。
    MOSQ_ERR_PAYLOAD_SIZE 如果payloadlen太大。
    MOSQ_ERR_MALFORMED_UTF8 如果主题无效,则为UTF-8
    MOSQ_ERR_QOS_NOT_SUPPORTED 如果QoS大于代理支持的QoS。
    MOSQ_ERR_OVERSIZE_PACKET 如果结果包大于代理支持的包。

10.断开MQTT代理/服务器

int mosquitto_disconnect( struct mosquitto * mosq )
功能:断开与代理/服务器的连接。
返回:
    MOSQ_ERR_SUCCESS 成功。
    MOSQ_ERR_INVAL 如果输入参数无效。
    MOSQ_ERR_NO_CONN 如果客户端未连接到代理。 

主函数代码如下

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include "mqtt_get_config.h"
#include "mosquitto.h"
#include "cJSON.h"

#define KEEPALIVE       60
#define PATH            "./config.ini"

int get_devsn(char *devsn, int size);
int get_time(char *date_time, int size);
int dht11_get_temperature(float *temp);
void mosq_connect_callback(struct mosquitto *mosq, void *obj, int rc);

int main(int argc, char *argv[])
{
    int                 rv = 0;
    struct mosquitto   *mosq = NULL;
    mqtt_user_data_t    mqtt;
    int                 rc = 0;
    void                *obj = NULL;
    float               temp = 0;
    cJSON               *cjson = NULL;
    cJSON               *root = NULL;
    char                *str = NULL;
    char                devsn_buf[8] = {0};
    char                time_buf[32] = {0};
    
    memset(&mqtt, 0, sizeof(mqtt));
    rv = get_config(PATH, &mqtt, PUB);
    printf("1-%s\n 2-%d\n 3-%s\n 4-%s\n 5-%s\n 6-%s\n",mqtt.brokeraddress,mqtt.brokerport,mqtt.username,mqtt.password,mqtt.clientid,mqtt.identifier);

    if(rv)
    {
        printf("get config\n");
    }

    rv = mosquitto_lib_init();
    if (rv < 0)
    {
        printf("mosquitto init failed: %s\n", strerror(errno));
        goto cleanup;
    }

    mosq = mosquitto_new(mqtt.clientid, true, (void *)&mqtt);
    if ( !mosq )
    {
        printf("mosquitto create failed: %s\n", strerror(errno));
        goto cleanup;
    }
    
    rv = mosquitto_username_pw_set(mosq, mqtt.username, mqtt.password);
    if(rv != MOSQ_ERR_SUCCESS)
    {
        printf("mqtt set failed\n");
    }
    printf("Create mosquitto successfully!\n");

    mosquitto_connect_callback_set(mosq, mosq_connect_callback);
    
    rv = mosquitto_connect(mosq, mqtt.brokeraddress, mqtt.brokerport, KEEPALIVE);
    if( rv != MOSQ_ERR_SUCCESS)
    {
        printf("mosquitto connect failed: %s\n", strerror(errno));
    }
    mosquitto_loop_start(mosq);

    while(1)
    {
        memset(devsn_buf, 0, sizeof(devsn_buf));
        rv = get_devsn(devsn_buf, sizeof(devsn_buf));
        if (rv)
        {
            printf("get devsn failed\n");
            return 0;
        }

        memset(time_buf, 0, sizeof(time_buf));
        rv = get_time(time_buf, sizeof(time_buf));
        if (rv)
        {
            printf("get time failed\n");
            return 0;
        }

        rv = dht11_get_temperature(&temp);
        if(rv)
        {
            printf("get temperature failed\n");
            return 0;
        }

        cjson = cJSON_CreateObject();
        root  = cJSON_CreateObject();

        cJSON_AddStringToObject(cjson, "method", mqtt.method);
        cJSON_AddStringToObject(cjson, "id", devsn_buf);
        cJSON_AddStringToObject(cjson, "time", time_buf);
        cJSON_AddNumberToObject(root, "CurrentTemperature", temp);
        cJSON_AddItemToObject(cjson, "params", root);
        cJSON_AddStringToObject(cjson, "version", mqtt.version);
        
        str = cJSON_Print(cjson);
        printf("%s\n", str);

        rv = mosquitto_publish(mosq, NULL, mqtt.topic, strlen(str), str, 0, true);
        if(rv != MOSQ_ERR_SUCCESS)
        {
            printf("mosquitto publish failed: %s\n", strerror(errno));
            return 0;
        }
            sleep(5);
    }

    mosquitto_disconnect(mosq);
    return 0;

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

int get_devsn(char *devsn, int size)
{
	strncpy(devsn, "0001", size);
	return 0;
}

int get_time(char *date_time, int size)
{
	time_t		utc_time;
	struct tm   dt;
	char       *wday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

	time(&utc_time);
	localtime_r(&utc_time, &dt);
	snprintf(date_time, size, "%04d-%02d-%02d--%s--%02d:%02d:%02d", 1900+dt.tm_year, 1+dt.tm_mon, dt.tm_mday, wday[dt.tm_wday], dt.tm_hour, dt.tm_min, dt.tm_sec);
	
	return 0;
}

int dht11_get_temperature(float *temp)
{
    int fd = 0;
    int length = 0;
    char buf[6] = {0};
    float a = 0;
    fd = open("/dev/dht11", O_RDONLY);
    if(fd < 0)
    {
        printf("open fail\n");
        return -1;
    }
    length = read(fd, buf, 6);
    if( length < 0)
    {
        printf("open fail\n");
        return -2;
    }
    a = buf[2]*10 + buf[3];  
    *temp = a/10;
    close(fd);
    return 0;
}

void mosq_connect_callback(struct mosquitto *mosq, void *obj, int rc)
{
       printf("connect sucessfully\n");
}

 gitee仓库:mqtt-aliyun: 使用mosquitto连接阿里云

可见温度实时上报


总结

连接阿里云使用Mosquitto进行MQTT通信的步骤为:创建阿里云公共实例、下载安装Mosquitto客户端、配置连接参数、进行发布操作。可见,我们可以采集不同的数据通过MQTT协议上报到阿里云。

        

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要将ESP8266连接阿里云,需要先创建一个阿里云账户并设置IoT平台,然后在IoT平台中创建一个设备和一个Topic,并为设备生成一个身份验证信息(DeviceSecret)。 然后,使用ESP8266开发板和MQTT(例如PubSubClient)连接阿里云。下面是连接步骤: 1. 在代码中引用MQTT和WiFi。 2. 设置WiFi连接参数并连接到WiFi网络。 3. 设置阿里云MQTT服务器地址和端口号。 4. 设置设备ID和DeviceSecret。 5. 连接MQTT服务器并订阅Topic。 6. 在循环中发送和接收MQTT消息。 下面是一些示例代码,你可以根据自己的情况进行修改: ```C++ #include <ESP8266WiFi.h> #include <PubSubClient.h> // WiFi连接参数 const char* ssid = "your_SSID"; const char* password = "your_PASSWORD"; // 阿里云MQTT服务器地址和端口 const char* mqtt_server = "your_server_address"; const int mqtt_port = 1883; // 设备ID和DeviceSecret const char* client_id = "your_device_id"; const char* device_secret = "your_device_secret"; // Topic const char* topic = "/your_topic"; // WiFi客户端 WiFiClient espClient; // MQTT客户端 PubSubClient client(espClient); void setup() { // 启动串口 Serial.begin(115200); // 连接WiFi网络 WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("WiFi connected"); // 设置MQTT服务器和端口 client.setServer(mqtt_server, mqtt_port); // 设置MQTT回调函数 client.setCallback(callback); // 连接MQTT服务器 if (!client.connect(client_id, device_secret)) { Serial.println("Failed to connect to MQTT server"); return; } // 订阅Topic client.subscribe(topic); } void loop() { // 发送MQTT消息 client.publish(topic, "Hello from ESP8266"); // 接收MQTT消息 client.loop(); } // MQTT回调函数 void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message received: "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); } ``` 在你的阿里云控制台中,你可以查看设备的连接状态和收到的消息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热爱跑流水灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值