0°

(八)ESP32:通过MQTT发送JSON消息

这篇文章的目的是解释如何使用ESP32通过MQTT发送JSON消息。

介绍

这篇文章的目的是解释如何使用ESP32通过MQTT发送JSON消息。

为此,我们将使用两个处理低级细节的库,并在易于使用的界面中向我们展示JSON编码和MQTT发布功能。这些库是PubSubClient,为MQTT提供相关的功能,以及ArduinoJson,为JSON提供相关的功能。

这两个库都可以与ESP8266和ESP32配合使用,并有一些示例可以帮助我们入门,我建议您尝试一下。此外,我一直在以前的帖子中介绍它们在两个设备中的使用情况,这些信息在相关帖子部分列出。

在这个教程中,我们将使用CloudMQTT,它提供免费计划,允许我们创建帐户并测试实例。如果您还没有注册,请注册并创建一个实例。我们将需要后者的实例信息(地址端口用户名密码)。

代码

我们需要做的第一件事是安装ArduinoJson.hPubSubClient.h库,以便能够访问所需的所有类。我们还需要包含WiFi.h库,这样我们就可以连接到WiFi网络,从而能够将消息发布到MQTT主题。

为了使代码更易读和易于修改,我们将声明一些全局变量来保存连接到WiFi网络和MQTT代理所需的凭据。对于与MQTT代理的连接,我们需要有关所创建实例的信息,该信息可在CloudMQTT实例信息页面中找到:

#include <ArduinoJson.h>
#include <WiFi.h>
#include <PubSubClient.h>
 
const char* ssid = yourNetworkName";
const char* password = "yourNetworkPassword";
 
const char* mqttServer = "m11.cloudmqtt.com";
const int mqttPort = 12948;
const char* mqttUser = "yourInstanceUsername";
const char* mqttPassword = "yourInstancePassword";

之后,我们将声明一个WiFiClient类的对象。我们还将声明类PubSubClient的对象,该对象 接收构造函数的输入以前声明的WiFiClient实例。请注意,我们不会在代码中使用WiFiClient,因为它将由PubSubClient库替代使用。因此,我们不需要担心实现细节:

WiFiClient espClient;
PubSubClient client(espClient);

声明全局变量后,我们将定义setup()函数。我们要做的第一件事就是打开一个串行连接,,设置好波特率。然后,我们连接到WiFi网络:

WiFi.begin(ssid, password);
 
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.println("Connecting to WiFi..");
}
 
Serial.println("Connected to the WiFi network");

接下来,我们需要指定要连接的MQTT代理的地址和端口。为此,我们 在PubSubClient对象上调用setServer方法,将地址和端口作为输入传递。这些参数是指定为全局变量并从CloudMQTT实例页面信息获取的参数。

现在,我们将通过调用connect方法连接到MQTT服务器。该方法接收一个字符串作为输入,该字符串对应于客户端的唯一标识符(我们将使用“ESP32Client”)。它还接收连接到代理所需的用户名和密码,可在CloudMQTT实例页面信息中获得。

此方法调用将在连接成功时返回true,否则返回false。我们将在循环中进行连接尝试:

while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
 
    if (client.connect("ESP32Client", mqttUser, mqttPassword )) {
 
      Serial.println("connected");
 
    } else {
 
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
 
    }
  }

在此之后,我们应该已经连接到MQTT代理,我们可以开始向主题发布消息。不过,我们将在主循环函数上执行此操作,因此我们在setup函数上不需要更多代码。

现在,在主循环函数中,我们声明了一个StaticJsonBuffer类的对象,它将用于创建要通过MQTT发送的JSON消息。我们需要指定缓冲区的容量(以字节为单位)作为模板参数。然后,我们通过调用createObject方法从我们创建的StaticJsonBuffer对象获得对JsonObject的引用。

StaticJsonBuffer<300> JSONbuffer;
JsonObject& JSONencoder = JSONbuffer.createObject();

我们将创建一个JSON消息,如下所示。请注意,我们将创建一个包含静态内容的消息,仅用于保持代码简单,但我们可以从传感器或其他动态源获取值。

 {
"device": "ESP32",
"sensorType" : "Temperature",
"Value" : [20,21,23]
}

接下来,我们将值添加到JsonObject中:

JSONencoder["device"] = "ESP32";
JSONencoder["sensorType"] = "Temperature";
JsonArray& values = JSONencoder.createNestedArray("values");
 
values.add(20);
values.add(21);
values.add(23);

现在,我们将使用 JsonObject引用上的printTo方法将JSON消息打印到char缓冲区 。此方法以紧凑格式打印消息,因此可以减少内存占用。

char JSONmessageBuffer[100];
JSONencoder.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));

接下来,我们将JSON消息发送到名为“ esp / test ” 的主题。我们通过调用 PubSubClient对象上的publish方法来实现。此方法将接收主题名称和我们要发布的消息作为输入。

从这里可以看出,如果发布成功,则此方法返回“true”,否则返回“false”。我们将使用此信息进行错误处理。

最后,我们在同一个对象引用上调用loop方法。这应该定期调用,以便我们的程序可以处理传入的消息并维护与MQTT服务器的连接。由于我们将在Arduino主循环函数中发送消息,每个消息之间有一个小延迟,我们在每次迭代结束时调用循环方法。

Serial.println(JSONmessageBuffer);
 
if (client.publish("esp/test", JSONmessageBuffer) == true) {
    Serial.println("Success sending message");
} else {
    Serial.println("Error sending message");
}
 
client.loop();

下面是最终完整代码,以及一些其他打印来帮助调试:

#include <ArduinoJson.h>
#include <WiFi.h>
#include <PubSubClient.h>
 
const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";
const char* mqttServer = "m11.cloudmqtt.com";
const int mqttPort = 12948;
const char* mqttUser = "yourInstanceUsername";
const char* mqttPassword = "yourInstancePassword";
 
WiFiClient espClient;
PubSubClient client(espClient);
 
void setup() {
 
  Serial.begin(115200);
  Serial.println();
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
 
  Serial.println("Connected to the WiFi network");
 
  client.setServer(mqttServer, mqttPort);
 
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
 
    if (client.connect("ESP32Client", mqttUser, mqttPassword )) {
 
      Serial.println("connected");
 
    } else {
 
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
 
    }
  }
 
}
 
void loop() {
 
  StaticJsonBuffer<300> JSONbuffer;
  JsonObject& JSONencoder = JSONbuffer.createObject();
 
  JSONencoder["device"] = "ESP32";
  JSONencoder["sensorType"] = "Temperature";
  JsonArray& values = JSONencoder.createNestedArray("values");
 
  values.add(20);
  values.add(21);
  values.add(23);
 
  char JSONmessageBuffer[100];
  JSONencoder.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
  Serial.println("Sending message to MQTT topic..");
  Serial.println(JSONmessageBuffer);
 
  if (client.publish("esp/test", JSONmessageBuffer) == true) {
    Serial.println("Success sending message");
  } else {
    Serial.println("Error sending message");
  }
 
  client.loop();
  Serial.println("-------------");
 
  delay(10000);
 
}

测试结果

为了测试代码,我们将使用MQTTLens软件来订阅ESP32将要发布的主题。因此,打开应用程序并订阅“ esp / test ”主题。

之后,将代码上传到ESP32并打开串行监视器。你可以看到类似于图1的输出。

ESP32:通过MQTT发送JSON消息

图1 – 程序的输出。

现在,回到MQTTLens。您可以看到类似于图2的输出,并打印JSON消息。MQTTLens识别JSON格式,虽然我们以紧凑格式发送消息,但它允许我们以缩进的用户友好格式查看它。

ESP32:通过MQTT发送JSON消息

图2 – ESP32发送的JSON消息。

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论