使用MQTT通过WiFi传输数据



MQTT(消息队列遥测传输)在物联网设备中获得了广泛的关注。它是一个通常在TCP/IP上运行的协议。与我们之前看到的HTTP的服务器-客户端模型不同,MQTT使用代理-客户端模型。维基百科将MQTT代理和客户端定义为:

MQTT代理是接收来自所有客户端的所有消息,然后将消息路由到相应的目标客户端的服务器。MQTT客户端是任何运行MQTT库并通过网络连接到MQTT代理的设备(从微控制器到功能齐全的服务器)。

将代理想象成类似Medium的服务。主题就是Medium上的出版物,客户端就是Medium的用户。用户(客户端)可以向出版物发布内容,订阅该出版物(主题)的另一个用户(客户端)将被告知有新的帖子可供阅读。到目前为止,您应该已经理解了HTTP和MQTT之间的一个主要区别。在HTTP中,您的消息直接发送到目标服务器,您甚至会以状态代码的形式获得确认。在MQTT中,您只是将消息发送到代理,希望您的目标服务器能够从中获取信息。如果您资源受限,MQTT的几个特性将成为一大福音。它们列在下面:

  • 使用MQTT,报头开销非常短,吞吐量很高。这有助于节省时间和电池电量。

  • MQTT将信息发送为字节数组,而不是文本格式。这使消息更轻量级。

  • 因为MQTT不依赖于服务器的响应,客户端是独立的,并且可以在传输消息后进入睡眠状态(节省电池电量)。

这些只是一些导致MQTT流行的原因。您可以在这里找到MQTT和HTTP之间更详细的比较这里

代码演练

通常,测试MQTT需要您在代理商注册免费/付费帐户。AWS IoT和Azure IoT是非常流行的提供MQTT代理服务的平台,但它们需要冗长的注册和配置过程。幸运的是,有一个来自HiveMQ的免费代理服务,可用于在无需注册或配置的情况下测试MQTT。它非常适合那些MQTT新手,只想动手实践的人,并且还可以让您更专注于ESP32的固件。因此,我们将在此章节中使用该代理。当然,因为它是一项免费服务,所以会有一些限制。您不能共享敏感信息,因为所有消息都是公开的,任何人都可以订阅您的主题。当然,对于测试目的,这些限制无关紧要。

代码可在GitHub上找到

我们将使用PubSubClient库。您可以从工具->管理库中安装它。

PubSubClient Library Install

安装库后,我们包含WiFi和PubSubClient库。

#include <WiFi.h>
#include <PubSubClient.h>

接下来,我们将定义一些常量。请记住替换WiFi凭据。mqttServer和mqttPort是由http://www.mqtt−dashboard.com/强制规定的。mqtt_client_name、mqtt_pub_topic和mqtt_sub_topic可以是您选择的任何字符串。只需确保您更改了它们的值。如果多个用户从本教程复制相同的代码,您将在测试时收到许多来自未知客户端的消息。

我们还定义了WiFiClient和mqttClient对象。MQTTClient对象需要网络客户端作为参数。如果您使用以太网,则会提供以太网客户端作为参数。由于我们使用的是WiFi,因此我们提供了WiFi客户端作为参数。

const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

//The broker and port are provided by http://www.mqtt−dashboard.com/
char *mqttServer = "broker.hivemq.com";
int mqttPort = 1883;

//Replace these 3 with the strings of your choice
const char* mqtt_client_name = "ESPYS2111";
const char* mqtt_pub_topic = "/ys/testpub"; //The topic to which our client will publish
const char* mqtt_sub_topic = "/ys/testsub"; //The topic to which our client will subscribe

WiFiClient client;
PubSubClient mqttClient(client);

接下来,我们定义回调函数。回调函数是一个中断函数。每当从订阅的主题接收到新消息时,都会触发此函数。它有三个参数:接收消息的主题、作为字节数组的消息以及消息的长度。您可以对该消息执行任何操作(将其存储在SPIFFS中,发送到另一个主题等)。在这里,我们只是打印主题和消息。

void callback(char* topic, byte* payload, unsigned int length) {
   Serial.print("Message received from: "); Serial.println(topic);
   for (int i = 0; i < length; i++) {
      Serial.print((char)payload[i]);
   }
   Serial.println();
   Serial.println();
}

在setup中,我们像其他每个草图一样连接到WiFi。最后两行与MQTT有关。我们设置MQTT的服务器和端口,以及回调函数。

void setup() {
   // put your setup code here, to run once:
   Serial.begin(115200);
   WiFi.mode(WIFI_STA);                    //The WiFi is in station mode
   WiFi.begin(ssid, password);
   while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
   }
   Serial.println("");  Serial.print("WiFi connected to: "); Serial.println(ssid);  Serial.println("IP address: ");     Serial.println(WiFi.localIP());
   delay(2000);
   mqttClient.setServer(mqttServer, mqttPort);
   mqttClient.setCallback(callback);
}

在循环中,我们执行以下操作

  • 如果客户端未连接到代理,我们使用客户端名称连接它。

  • 连接后,我们还将客户端订阅到mqtt_sub_topic。

  • 然后,我们将消息发布到mqtt_pub_topic

  • 然后我们运行**mqttClient.loop()**。此loop()函数应定期调用。它维护客户端与代理的连接,并帮助客户端处理传入的消息。如果您没有这行**mqttClient.loop()**代码,您将能够发布到mqtt_pub_topic,但不会收到来自mqtt_sub_topic的消息,因为只有调用此行时才会处理传入的消息。

  • 最后,我们等待5秒钟,然后再次启动此循环。

void loop() {
   // put your main code here, to run repeatedly:
   if (!mqttClient.connected()){
      while (!mqttClient.connected()){
         if(mqttClient.connect(mqtt_client_name)){
            Serial.println("MQTT Connected!");
            mqttClient.subscribe(mqtt_sub_topic);
         }
         else{
            Serial.print(".");
         }
      }
   }
   mqttClient.publish(mqtt_pub_topic, "TestMsg");
   Serial.println("Message published");
   mqttClient.loop();
   delay(5000);
}

测试代码

为了测试上述代码,您需要访问www.hivemq.com

在该网页上之后,请按照以下步骤操作:

  • 单击“连接”

Connect Websocket Client
  • 单击“添加新的主题订阅”,然后输入ESP32将发布到的主题名称(在本例中为/ys/testpub)

Subscribe to a Topic
  • 刷新ESP32后,您将每5秒开始接收该主题上的消息。

View Messages
  • 接下来,要测试ESP32上的消息接收,请输入ESP32订阅的主题名称(在本例中为ys/testsub),然后在消息框中键入消息并单击发布。您应该在串口监视器上看到该消息。
ESP32 Subscribe Test

恭喜!!您已在ESP32上使用MQTT测试了发布和订阅。

参考文献

广告