ESP32+idf开发之WIFI通信入门(4)MQTT通信

ESP32+idf开发之WIFI通信入门(4)MQTT通信

一、实现功能:

1、esp32作为MQTT客户端定时每隔2秒向MQTT服务端发布消息:

​ topic:heartbeat

​ payload:client1 is online!

2、esp32作为MQTT客户端订阅主题为“/control”,接收该主题的消息payload并打印。

二、MQTT概述:

​ MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的轻量级协议,该协议构建于TCP/IP协议之上,MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。MQTT协议是一个基于客户端-服务器的消息发布/订阅传输协议。它是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛,作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。

image-20230325221648666

MQTT有三种消息发布服务质量:

“至多一次”,消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。这一种方式主要普通APP的推送,倘若你的智能设备在消息推送时未联网,推送过去没收到,再次联网也就收不到了。

“至少一次”,确保消息到达,但消息重复可能会发生。

​ “只有一次”,确保消息到达一次。在一些要求比较严格的计费系统中,可以使用此级别。在计费系统中,消息重复或丢失会导致不正确的结果。这种最高质量的消息发布服务还可以用于即时通讯类的APP的推送,确保用户收到且只会收到一次。

实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。

MQTT传输的消息分为:主题(Topic)和负载(payload)两部分:

(1)topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload);

(2)payload,可以理解为消息的内容,是指订阅者具体要使用的内容。

MQTT服务器可用免费共享的,也可自行搭建,本测试采用的在云服务器上自行搭建EMQX服务器(https://www.emqx.io/zh/downloads)

三、步骤:

1、复制wifi连接的组件代码到工程的自定义组件(components)中,进入vscode创建示例空项目,打开命令终端:

mkdir components

cp -r D:\Espressif\frameworks\esp-idf-v4.4.1\examples\common_components\protocol_examples_common .\components

2、配置wifi连接设置,打开终端命令界面输入idf.py menuconfig,进入到Example Connection Configuration界面对热点信息的ssid和password等配置。

image-20230321221245559

3、在main.c中编写实现以上功能的代码:

#include <esp_log.h>
#include <esp_system.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

#include <nvs_flash.h>
#include <esp_netif.h>
#include <esp_event.h>
#include <protocol_examples_common.h>
#include <mqtt_client.h>

static char *TAG = "mqtt_client";

static esp_mqtt_client_handle_t mqttclient;
static bool connect_flag = false; // 定义一个连接上mqtt服务器的flag

// mqtt的状态机事件处理函数
static void mqtt_event_handler(void *args, esp_event_base_t base, int32_t id, void *event_data)
{
    esp_mqtt_event_t *client_event = event_data;
    esp_mqtt_event_id_t client_id = id;

    switch (client_id)
    {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "connected to mqtt_server");
        connect_flag = true;
        esp_mqtt_client_subscribe(mqttclient, "control", 2); // 订阅一个/control的topic
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "disconnected");
        connect_flag = false;
        break;
    case MQTT_EVENT_DATA:
    {
        char topic[128] = {};
        char data[512] = {};
        memcpy(topic, client_event->topic, client_event->topic_len);
        memcpy(data, client_event->data, client_event->data_len);
        printf("topic:%s\n", topic);
        printf("data:%s\n", data);
    }
    break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "error");
        connect_flag = false;
        break;

    default:
        break;
    }
}
void app_main(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    ESP_ERROR_CHECK(example_connect());

    // mqtt服务器的配置信息(根据实际情况填写)
    esp_mqtt_client_config_t cfg = {
        .uri = "mqtt://XX.XX.XX.XX",
        .port = XX,
        .username = "XX",
        .password = "XX",
    };

    mqttclient = esp_mqtt_client_init(&cfg);

    //注册MQTT状态机事件处理回调函数
    esp_mqtt_client_register_event(mqttclient, MQTT_EVENT_ANY, mqtt_event_handler, NULL);

    esp_mqtt_client_start(mqttclient);

    while (1)
    {
        if (connect_flag == true)
        {
            char buff[512] = "client1 is online!";
            // 向mqtt服务器发布主题为/heartbeat/1,payload为buff的数据
            esp_mqtt_client_publish(mqttclient, "heartbeat", buff, strlen(buff), 2, 0); 
        }

        vTaskDelay(pdMS_TO_TICKS(2000));
    }
}

四、测试:

编译、烧写、监控esp32,用另一个MQTT客户端(如通信猫)来进行订阅/发布测试,在通信猫上可每两秒接收到esp32发布的消息,在esp32上可打印出通信猫发布的消息。

image-20230325224441659

image-20230325224609860

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值