ESP32 SDK
本文主要介绍如何在ESP32项目中使用 PubSubClient
,实现ESP32客户端与WaveshareCloud的连接、订阅、收发消息等功能
本文将分别介绍通过 TCP 端口和 SSL/TLS 端口来连接 ESP32 客户端到 MQTT 服务器。TCP 端口和 SSL/TLS 端口连接在连接设置部分略有不同,发布和订阅部分代码相同。
前置准备
获取连接参数
通过登录WaveshareCloud 设备|属性列表创建一个可用的设备之后,点击右侧黄色: 查看地址获得相关信息
示例:
MqttPath: mqtt.waveshare.cloud
Port: 1883
Client ID: 052405b2
Pub Topic: Pub/10/16/052405b2
Sub Topic: Sub/10/16/052405b2
Arduino IDE
本文中使用 Arduino IDE 作为代码编辑和上传
安装依赖
在 Arduino IDE 中完成以下安装。
安装 ESP32 开发板。
点击工具-> 开发板-> 开发板管理 。搜索 ESP32,点击安装。
安装 PubSub client 库。
点击项目-> 加载库-> 管理库... 。搜索 PubSubClient
,安装 PubSubClient by Nick O’Leary。
连接方式
设置MQTT 连接地址、端口、主题、客户端ID
const char* mqtt_server = "mqtt.waveshare.cloud";
int PORT = 1883;
const char* ID = "052405b2"; // 定义设备 ID
char sub[] = "Sub/10/16/052405b2"; // MQTT 订阅主题
char pub[] = "Pub/10/16/052405b2"; // MQTT 发布主题
设置MQTTS 连接地址、端口、主题、客户端ID
通过复制CA证书到本地在代码中加载证书
const char* mqtt_server = "mqtt.waveshare.cloud"; int PORT = 8883; const char* ID = "052405b2"; // 定义设备 ID char sub[] = "Sub/10/16/052405b2"; // MQTT 订阅主题 char pub[] = "Pub/10/16/052405b2"; // MQTT 发布主题 WiFiClientSecure espClient; // 设置ESP32开启SSL/TLS连接免证书方式在setup函数初始化时添加以下代码
espClient.setInsecure();
设置MQTTS 连接地址、端口、主题、客户端ID
通过复制CA证书到本地在代码中加载证书
const char* mqtt_server = "mqtt.waveshare.cloud"; int PORT = 8884; const char* ID = "052405b2"; // 定义设备 ID char sub[] = "Sub/10/16/052405b2"; // MQTT 订阅主题 char pub[] = "Pub/10/16/052405b2"; // MQTT 发布主题 WiFiClientSecure espClient; // 设置ESP32开启SSL/TLS连接将证书以字符串形式加载到代码中
const char* root_ca = \ "-----BEGIN CERTIFICATE-----\n" "MIID6TCCAtGgAwIBAgIJALAks3ODRL3nMA0GCSqGSIb3DQEBCwUAMIGKMQswCQYD\n" "VQQGEwJjbjELMAkGA1UECAwCZ2QxCzAJBgNVBAcMAnN6MRIwEAYDVQQKDAl3YXZl\n" "c2hhcmUxDDAKBgNVBAsMA2lvdDEdMBsGA1UEAwwUbXF0dC53YXZlc2hhcmUuY2xv\n" "dWQxIDAeBgkqhkiG9w0BCQEWEXN3YW5zaGFyZUAxNjMuYzBtMB4XDTIzMTAyNjAy\n" "MzgxMVoXDTMzMTAyMzAyMzgxMVowgYoxCzAJBgNVBAYTAmNuMQswCQYDVQQIDAJn\n" "ZDELMAkGA1UEBwwCc3oxEjAQBgNVBAoMCXdhdmVzaGFyZTEMMAoGA1UECwwDaW90\n" "MR0wGwYDVQQDDBRtcXR0LndhdmVzaGFyZS5jbG91ZDEgMB4GCSqGSIb3DQEJARYR\n" "c3dhbnNoYXJlQDE2My5jMG0wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n" "AQDUoDxq2kCRWqhvFvOTOrYSwbw0LIfgN5zqxXTqU36bM0wsuPVm3to0M3A+LU7t\n" "2WEL81WIgmN4Lb8fBDCEw+O3c+7Cjv3kUvkD0RZVWQgTYWIVYV+OfvwRBSAkIXl9\n" "he8VBXJ9nLi4XcSVYKSGCXw63hOJ23EODCTeKKIzfKlwq0o5d90AOz7Yet9AMqLw\n" "WvLRFTaA0oFj3rlsoigmKVQ0QIa+Dt9GZQrmGKyu27tjR067oMLSRHQRtamSuVO/\n" "wz30S1FH0T59hA30Xc8mekQT9qkPZJeY9w7wp8w3wMqnquZpn3n1ESCKZMpJnwqJ\n" "0dip3TfyNVI0nPGmEOqKejcbAgMBAAGjUDBOMB0GA1UdDgQWBBQKOKe2XoqfgLVa\n" "2bNxZ5eeKBEMazAfBgNVHSMEGDAWgBQKOKe2XoqfgLVa2bNxZ5eeKBEMazAMBgNV\n" "HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAdvB90XePwNx/KRINFwTtBj9cP\n" "VFSCWccGjQgNQoxKXKRmWoIbUAXtoVjzFAqc2t9Blcw9HNIeR5bt+Cw5AYrqnw41\n" "z+ZqJ3D6j1S+YGaAnN/8PQRDDl2/cTw/6CDf+iyVI/FPcFcMcNTFFrwII4/3V4sn\n" "OoO+7MuCHH3sEliEef+FqIiP0UKeWLlGPJLRidcc1416ksrfeHGdkBrQTJ2gZfFC\n" "j+sRHaFesqEQhDzNUpQ0bXgIivWLiPrA+dwcBp+oq4o4hpZIddDD33JaAxGkUM9B\n" "4k0kEUml0o8NWGVHPdueLq5srczFfw2AHiUPyKCje9RjPNq6TvBCG9n9aznV\n" "-----END CERTIFICATE-----"; const char* server_crt = \ "-----BEGIN CERTIFICATE-----\n" "MIIDkjCCAnoCCQDLHlw5O4wZlTANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMC\n" "Y24xCzAJBgNVBAgMAmdkMQswCQYDVQQHDAJzejESMBAGA1UECgwJd2F2ZXNoYXJl\n" "MQwwCgYDVQQLDANpb3QxHTAbBgNVBAMMFG1xdHQud2F2ZXNoYXJlLmNsb3VkMSAw\n" "HgYJKoZIhvcNAQkBFhFzd2Fuc2hhcmVAMTYzLmMwbTAeFw0yMzEwMjYwMjQ2NTla\n" "Fw0yNDEwMjUwMjQ2NTlaMIGKMQswCQYDVQQGEwJjbjELMAkGA1UECAwCZ2QxCzAJ\n" "BgNVBAcMAnN6MRIwEAYDVQQKDAl3YXZlc2hhcmUxDDAKBgNVBAsMA2lvdDEdMBsG\n" "A1UEAwwUbXF0dC53YXZlc2hhcmUuY2xvdWQxIDAeBgkqhkiG9w0BCQEWEXN3YW5z\n" "aGFyZUAxNjMuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA28+u\n" "XDwxDevoWHyWECp2cvOAFuttb0oBDfiwgBuJrnizn1iBlhmtxKBXjT5+L1P2aPAs\n" "AoB5boe7Q4RAwpnXi8fW7/mmh+tahtJtb3TvKEdvACbitwg6ZkwbuOv10YuI+OT3\n" "H8cOSdERm6oCXP0TtlE8T6tQ2d2CdBV34+nWLCOEjDHOBhIO43g6hC+/zIZRUOqw\n" "qQxRkryl7cBs2gqd8O964FQfC3WXtiOQoJohsWIScUQMrQ2UZ/A/Bb8gC6lJhi8C\n" "TvvJavbXP4DwU16ZRPyW2fq24xflew3yD/0bXjQCD9JhhwpCmjkE0/XHbCUrfHmD\n" "NOASvFRV/oPkPT/kHwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCxnd1adIlwI8Ta\n" "rKP1Ajb/4FHDYLZwqqQqD2y2/Edd2RChOFkv8MhkkKZEBToWd/5+xFDZMmOLy+/S\n" "zl2FRGMbenXTy9/IDhJioctm6+BGkRaM5OskqLnyugJr7sHqEnS9Un/aGjhxbV+4\n" "tGKXW7ZUyRwgf82sKDAZ6hdJ65d6Qe4Jp2Z19pdv0sm4mYgKir/QAuW+dnH7FEAg\n" "kR9M38iXvgTNx9vcrCztwxivvnVuFlbm2Nt17GrNusN8g6D0ipymJ16PUaUI7tk3\n" "tBSkdjFLg6NVsV2hw/7Kcvw1gOdzXs1uOrZIQbFGSHbbIgzlsWaA8S3gsw3L4YZb\n" "6efBEiLC\n" "-----END CERTIFICATE-----"; const char* server_key = \ "-----BEGIN RSA PRIVATE KEY-----\n" "MIIEogIBAAKCAQEA28+uXDwxDevoWHyWECp2cvOAFuttb0oBDfiwgBuJrnizn1iB\n" "lhmtxKBXjT5+L1P2aPAsAoB5boe7Q4RAwpnXi8fW7/mmh+tahtJtb3TvKEdvACbi\n" "twg6ZkwbuOv10YuI+OT3H8cOSdERm6oCXP0TtlE8T6tQ2d2CdBV34+nWLCOEjDHO\n" "BhIO43g6hC+/zIZRUOqwqQxRkryl7cBs2gqd8O964FQfC3WXtiOQoJohsWIScUQM\n" "rQ2UZ/A/Bb8gC6lJhi8CTvvJavbXP4DwU16ZRPyW2fq24xflew3yD/0bXjQCD9Jh\n" "hwpCmjkE0/XHbCUrfHmDNOASvFRV/oPkPT/kHwIDAQABAoIBAA4j9huI4775hiDr\n" "Itw3XxdWAs92pbubDyZO8UvMebb3nNaLYwq87CjSB8/WTVfOFvP5P1uJ2EX8BVf6\n" "kg/yxaMAYBtf/A6SXWh+8PtSknAM6F8iIUOVC+y4yK/EvjOUvmMEl8E7lPe6s19I\n" "OI6y2SnJYA/f/XuGfHXrS6Mlz9lW8RKd4r4KmvNgkyy2Yt21zec5bB7aJVuC9MV5\n" "+6f20S/EHbbAi1YbOPtcPOaoIkdtXO5PuSwFy8HER5jYOQp+RUT5xC8HoS+jJCF9\n" "5dCa9suSiw3vq0cNn91AIx+oU4lVrCNcVpX41aKsovk4wwuaOFinQqTN5k6xLNPq\n" "M+yrZgECgYEA7bKgW1EgCRK5M/WZZTQbTSW7iWVZanrccotyxIkYzGpgmQy8AYKj\n" "n2rpyeBXLwcBHPqdsWPVYSeEJJ9zbHxsBRxsX7MLvB5zRb0S05YVk0+x3YvDXhCy\n" "42MHcPPjxWDvRh16j1h+IwRsIpatQrZnnKBXAGc/w4jVLZ2sV43imH8CgYEA7Lx8\n" "PA/x9mSxBrjBIIpKQBlAcBzxT6z82AiDBfOG4Sf/P2fb/wNSRKVC/XeTh1Zczt1Z\n" "ovPJdVe8qGsqEaI54Zrhp2shGfkvTTh4WwI3km8jdcEtjtHaoUBYFzmFd+Rrv8Uj\n" "PWV5cfPmxbWG7GY9j6gudHgZE6iZLO1JtwPt5GECgYAfPvbzahOi/bIY0XUrp5Db\n" "MFWZtxfs9l+aMxiQG1GGNYmjNNhV/n1RzHUVE4eCaBJOY+ds1SnMjqxBQDClFyn/\n" "9f+NCPVG8l3G0hbyd204oyZHcELrT5ikaXUl9PmBDcAGYIOm6kQSiFdKqLH37hBq\n" "t20YYXoxUwBq8aohDEa4MwKBgBVgl99cmT7krM+sk1P66OWM4jK9ilTljBd9/Ubm\n" "TMG8OOJi4IzQofcs7TWyPJI2DD9p4ZRDa2e7OoAC3VOmUI+8yq+xjtWnmMviU4v0\n" "UUxZ2NvjS9ffv1xcURgXy6Od7tTsWlhK94KAwdAMqlhiiyCT0U4XIjySNvLFoqhy\n" "JGNBAoGAL/S8MY/eSrOwndafr/Oa+lHd7obuM9MuUsLzswhSJBZqnKAb+XGZCnEm\n" "I8hTk2hQm68nrKpw8121rqvWejHmkUzKlZJ45ixokfj3TOktzcxb5/kGfvRnRuzG\n" "nNwCNDQdC+lEfyiEoi8nuDEM0pR3emSWiUvI6QDDfER19psF62c=\n" "-----END RSA PRIVATE KEY-----";证书初始化设置
espClient.setCACert(root_ca); espClient.setCertificate(server_crt); espClient.setPrivateKey(server_key);
订阅和发布
订阅主题
订阅主题
client.subscribe(<Data>);
消息回调
void callback(char* topic, byte* payload, unsigned int length) {
String inputString;
for (int i = 0; i < length; i++) {
inputString += (char)payload[i];
}
Serial.println(inputString);
int dataBegin = inputString.indexOf("\"data\"");
if (dataBegin == -1) {
Serial.println(F("Missing 'data' field in JSON."));
return;
}
int builtInBegin = inputString.indexOf("\"builtIn\"", dataBegin);
if (builtInBegin == -1) {
Serial.println(F("Missing 'builtIn' field in 'data' object."));
return;
}
int valueBegin = inputString.indexOf(':', builtInBegin);
int valueEnd = inputString.indexOf('}', valueBegin);
if (valueBegin == -1 || valueEnd == -1) {
Serial.println(F("Invalid 'builtIn' value."));
return;
}
String builtInValueStr = inputString.substring(valueBegin + 1, valueEnd);
int builtInValue = builtInValueStr.toInt();
if (builtInValue == 0) {
Serial.println("close!");
} else {
Serial.println("open!");
}
}
发布主题
发布消息
client.publish(pub, <data>);
Json格式上发数据函数
void sendJsonData() {
sendJson["ID"] = ID;
String pubres;
serializeJson(sendJson, pubres);
int str_len = pubres.length() + 1;
char char_array[str_len];
pubres.toCharArray(char_array, str_len);
client.publish(pub, char_array);
}
完整代码
通过TCP端口连接
#include <ArduinoJson.h>
#include <Arduino.h>
#include <PubSubClient.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#define MSG_BUFFER_SIZE (50)
// WiFi 接入点的名称和密码
#define STASSID ""
#define STAPSK ""
const char* mqtt_server = "mqtt.waveshare.cloud";
int PORT = 1883;
const char* ID = ""; // 定义设备 ID
char sub[] = ""; // MQTT 订阅主题
char pub[] = ""; // MQTT 发布主题
StaticJsonDocument<400> sendJson;
StaticJsonDocument<400> readJson;
unsigned long lastUpdateTime = 0;
const char* ssid = STASSID;
const char* password = STAPSK;
char msg[MSG_BUFFER_SIZE];
WiFiClient espClient;
PubSubClient client(espClient);
const unsigned long updateInterval = 5000;
void setup() {
Serial.begin(9600);
setup_wifi();
client.setServer(mqtt_server, PORT);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
if (millis() - lastUpdateTime > updateInterval) { // 数据定时上报
sendJsonData();
lastUpdateTime = millis();
}
}
// MQTT 订阅回调函数,用于处理接收到的消息
void callback(char* topic, byte* payload, unsigned int length) {
String inputString;
for (int i = 0; i < length; i++) {
inputString += (char)payload[i];
}
Serial.println(inputString);
int dataBegin = inputString.indexOf("\"data\"");
if (dataBegin == -1) {
Serial.println(F("Missing 'data' field in JSON."));
return;
}
int builtInBegin = inputString.indexOf("\"builtIn\"", dataBegin);
if (builtInBegin == -1) {
Serial.println(F("Missing 'builtIn' field in 'data' object."));
return;
}
int valueBegin = inputString.indexOf(':', builtInBegin);
int valueEnd = inputString.indexOf('}', valueBegin);
if (valueBegin == -1 || valueEnd == -1) {
Serial.println(F("Invalid 'builtIn' value."));
return;
}
String builtInValueStr = inputString.substring(valueBegin + 1, valueEnd);
int builtInValue = builtInValueStr.toInt();
if (builtInValue == 0) {
Serial.println("close!");
} else {
Serial.println("open!");
}
}
void setup_wifi() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
// 重新连接 MQTT 服务器
void reconnect() {
while (!client.connected()) {
if (client.connect(ID)) {
client.subscribe(sub);
} else {
Serial.print(client.state());
delay(5000);
}
}
}
// 发送 JSON 格式的数据到 MQTT 服务器
void sendJsonData() {
sendJson["ID"] = ID;
String pubres;
serializeJson(sendJson, pubres);
int str_len = pubres.length() + 1;
char char_array[str_len];
pubres.toCharArray(char_array, str_len);
client.publish(pub, char_array);
}
通过SSL/TSL端口连接(免证书)
#include <ArduinoJson.h>
#include <Arduino.h>
#include <PubSubClient.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#define MSG_BUFFER_SIZE (50)
// WiFi 接入点的名称和密码
#define STASSID ""
#define STAPSK ""
const char* mqtt_server = "mqtt.waveshare.cloud";
int PORT = 8883;
const char* ID = ""; // 定义设备 ID
char sub[] = ""; // MQTT 订阅主题
char pub[] = ""; // MQTT 发布主题
StaticJsonDocument<400> sendJson;
StaticJsonDocument<400> readJson;
unsigned long lastUpdateTime = 0;
const char* ssid = STASSID;
const char* password = STAPSK;
char msg[MSG_BUFFER_SIZE];
WiFiClient espClient;
PubSubClient client(espClient);
const unsigned long updateInterval = 5000;
void setup() {
Serial.begin(9600);
setup_wifi();
espClient.setInsecure();
client.setServer(mqtt_server, PORT);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
if (millis() - lastUpdateTime > updateInterval) { // 数据定时上报
sendJsonData();
lastUpdateTime = millis();
}
}
// MQTT 订阅回调函数,用于处理接收到的消息
void callback(char* topic, byte* payload, unsigned int length) {
String inputString;
for (int i = 0; i < length; i++) {
inputString += (char)payload[i];
}
Serial.println(inputString);
int dataBegin = inputString.indexOf("\"data\"");
if (dataBegin == -1) {
Serial.println(F("Missing 'data' field in JSON."));
return;
}
int builtInBegin = inputString.indexOf("\"builtIn\"", dataBegin);
if (builtInBegin == -1) {
Serial.println(F("Missing 'builtIn' field in 'data' object."));
return;
}
int valueBegin = inputString.indexOf(':', builtInBegin);
int valueEnd = inputString.indexOf('}', valueBegin);
if (valueBegin == -1 || valueEnd == -1) {
Serial.println(F("Invalid 'builtIn' value."));
return;
}
String builtInValueStr = inputString.substring(valueBegin + 1, valueEnd);
int builtInValue = builtInValueStr.toInt();
if (builtInValue == 0) {
Serial.println("close!");
} else {
Serial.println("open!");
}
}
void setup_wifi() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
// 重新连接 MQTT 服务器
void reconnect() {
while (!client.connected()) {
if (client.connect(ID)) {
client.subscribe(sub);
} else {
Serial.print(client.state());
delay(5000);
}
}
}
// 发送 JSON 格式的数据到 MQTT 服务器
void sendJsonData() {
sendJson["ID"] = ID;
String pubres;
serializeJson(sendJson, pubres);
int str_len = pubres.length() + 1;
char char_array[str_len];
pubres.toCharArray(char_array, str_len);
client.publish(pub, char_array);
}
通过SSL/TSL端口连接(携带证书)
#include <ArduinoJson.h>
#include <Arduino.h>
#include <PubSubClient.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#define MSG_BUFFER_SIZE (50)
// WiFi 接入点的名称和密码
#define STASSID ""
#define STAPSK ""
const char* mqtt_server = "mqtt.waveshare.cloud";
int PORT = 8884;
const char* ID = ""; // 定义设备 ID
char sub[] = ""; // MQTT 订阅主题
char pub[] = ""; // MQTT 发布主题
StaticJsonDocument<400> sendJson;
StaticJsonDocument<400> readJson;
unsigned long lastUpdateTime = 0;
const char* ssid = STASSID;
const char* password = STAPSK;
char msg[MSG_BUFFER_SIZE];
WiFiClientSecure espClient;
PubSubClient client(espClient);
const unsigned long updateInterval = 5000;
const char* root_ca = \
"-----BEGIN CERTIFICATE-----\n"
"MIID6TCCAtGgAwIBAgIJALAks3ODRL3nMA0GCSqGSIb3DQEBCwUAMIGKMQswCQYD\n"
"VQQGEwJjbjELMAkGA1UECAwCZ2QxCzAJBgNVBAcMAnN6MRIwEAYDVQQKDAl3YXZl\n"
"c2hhcmUxDDAKBgNVBAsMA2lvdDEdMBsGA1UEAwwUbXF0dC53YXZlc2hhcmUuY2xv\n"
"dWQxIDAeBgkqhkiG9w0BCQEWEXN3YW5zaGFyZUAxNjMuYzBtMB4XDTIzMTAyNjAy\n"
"MzgxMVoXDTMzMTAyMzAyMzgxMVowgYoxCzAJBgNVBAYTAmNuMQswCQYDVQQIDAJn\n"
"ZDELMAkGA1UEBwwCc3oxEjAQBgNVBAoMCXdhdmVzaGFyZTEMMAoGA1UECwwDaW90\n"
"MR0wGwYDVQQDDBRtcXR0LndhdmVzaGFyZS5jbG91ZDEgMB4GCSqGSIb3DQEJARYR\n"
"c3dhbnNoYXJlQDE2My5jMG0wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n"
"AQDUoDxq2kCRWqhvFvOTOrYSwbw0LIfgN5zqxXTqU36bM0wsuPVm3to0M3A+LU7t\n"
"2WEL81WIgmN4Lb8fBDCEw+O3c+7Cjv3kUvkD0RZVWQgTYWIVYV+OfvwRBSAkIXl9\n"
"he8VBXJ9nLi4XcSVYKSGCXw63hOJ23EODCTeKKIzfKlwq0o5d90AOz7Yet9AMqLw\n"
"WvLRFTaA0oFj3rlsoigmKVQ0QIa+Dt9GZQrmGKyu27tjR067oMLSRHQRtamSuVO/\n"
"wz30S1FH0T59hA30Xc8mekQT9qkPZJeY9w7wp8w3wMqnquZpn3n1ESCKZMpJnwqJ\n"
"0dip3TfyNVI0nPGmEOqKejcbAgMBAAGjUDBOMB0GA1UdDgQWBBQKOKe2XoqfgLVa\n"
"2bNxZ5eeKBEMazAfBgNVHSMEGDAWgBQKOKe2XoqfgLVa2bNxZ5eeKBEMazAMBgNV\n"
"HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAdvB90XePwNx/KRINFwTtBj9cP\n"
"VFSCWccGjQgNQoxKXKRmWoIbUAXtoVjzFAqc2t9Blcw9HNIeR5bt+Cw5AYrqnw41\n"
"z+ZqJ3D6j1S+YGaAnN/8PQRDDl2/cTw/6CDf+iyVI/FPcFcMcNTFFrwII4/3V4sn\n"
"OoO+7MuCHH3sEliEef+FqIiP0UKeWLlGPJLRidcc1416ksrfeHGdkBrQTJ2gZfFC\n"
"j+sRHaFesqEQhDzNUpQ0bXgIivWLiPrA+dwcBp+oq4o4hpZIddDD33JaAxGkUM9B\n"
"4k0kEUml0o8NWGVHPdueLq5srczFfw2AHiUPyKCje9RjPNq6TvBCG9n9aznV\n"
"-----END CERTIFICATE-----";
const char* server_crt = \
"-----BEGIN CERTIFICATE-----\n"
"MIIDkjCCAnoCCQDLHlw5O4wZlTANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMC\n"
"Y24xCzAJBgNVBAgMAmdkMQswCQYDVQQHDAJzejESMBAGA1UECgwJd2F2ZXNoYXJl\n"
"MQwwCgYDVQQLDANpb3QxHTAbBgNVBAMMFG1xdHQud2F2ZXNoYXJlLmNsb3VkMSAw\n"
"HgYJKoZIhvcNAQkBFhFzd2Fuc2hhcmVAMTYzLmMwbTAeFw0yMzEwMjYwMjQ2NTla\n"
"Fw0yNDEwMjUwMjQ2NTlaMIGKMQswCQYDVQQGEwJjbjELMAkGA1UECAwCZ2QxCzAJ\n"
"BgNVBAcMAnN6MRIwEAYDVQQKDAl3YXZlc2hhcmUxDDAKBgNVBAsMA2lvdDEdMBsG\n"
"A1UEAwwUbXF0dC53YXZlc2hhcmUuY2xvdWQxIDAeBgkqhkiG9w0BCQEWEXN3YW5z\n"
"aGFyZUAxNjMuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA28+u\n"
"XDwxDevoWHyWECp2cvOAFuttb0oBDfiwgBuJrnizn1iBlhmtxKBXjT5+L1P2aPAs\n"
"AoB5boe7Q4RAwpnXi8fW7/mmh+tahtJtb3TvKEdvACbitwg6ZkwbuOv10YuI+OT3\n"
"H8cOSdERm6oCXP0TtlE8T6tQ2d2CdBV34+nWLCOEjDHOBhIO43g6hC+/zIZRUOqw\n"
"qQxRkryl7cBs2gqd8O964FQfC3WXtiOQoJohsWIScUQMrQ2UZ/A/Bb8gC6lJhi8C\n"
"TvvJavbXP4DwU16ZRPyW2fq24xflew3yD/0bXjQCD9JhhwpCmjkE0/XHbCUrfHmD\n"
"NOASvFRV/oPkPT/kHwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCxnd1adIlwI8Ta\n"
"rKP1Ajb/4FHDYLZwqqQqD2y2/Edd2RChOFkv8MhkkKZEBToWd/5+xFDZMmOLy+/S\n"
"zl2FRGMbenXTy9/IDhJioctm6+BGkRaM5OskqLnyugJr7sHqEnS9Un/aGjhxbV+4\n"
"tGKXW7ZUyRwgf82sKDAZ6hdJ65d6Qe4Jp2Z19pdv0sm4mYgKir/QAuW+dnH7FEAg\n"
"kR9M38iXvgTNx9vcrCztwxivvnVuFlbm2Nt17GrNusN8g6D0ipymJ16PUaUI7tk3\n"
"tBSkdjFLg6NVsV2hw/7Kcvw1gOdzXs1uOrZIQbFGSHbbIgzlsWaA8S3gsw3L4YZb\n"
"6efBEiLC\n"
"-----END CERTIFICATE-----";
const char* server_key = \
"-----BEGIN RSA PRIVATE KEY-----\n"
"MIIEogIBAAKCAQEA28+uXDwxDevoWHyWECp2cvOAFuttb0oBDfiwgBuJrnizn1iB\n"
"lhmtxKBXjT5+L1P2aPAsAoB5boe7Q4RAwpnXi8fW7/mmh+tahtJtb3TvKEdvACbi\n"
"twg6ZkwbuOv10YuI+OT3H8cOSdERm6oCXP0TtlE8T6tQ2d2CdBV34+nWLCOEjDHO\n"
"BhIO43g6hC+/zIZRUOqwqQxRkryl7cBs2gqd8O964FQfC3WXtiOQoJohsWIScUQM\n"
"rQ2UZ/A/Bb8gC6lJhi8CTvvJavbXP4DwU16ZRPyW2fq24xflew3yD/0bXjQCD9Jh\n"
"hwpCmjkE0/XHbCUrfHmDNOASvFRV/oPkPT/kHwIDAQABAoIBAA4j9huI4775hiDr\n"
"Itw3XxdWAs92pbubDyZO8UvMebb3nNaLYwq87CjSB8/WTVfOFvP5P1uJ2EX8BVf6\n"
"kg/yxaMAYBtf/A6SXWh+8PtSknAM6F8iIUOVC+y4yK/EvjOUvmMEl8E7lPe6s19I\n"
"OI6y2SnJYA/f/XuGfHXrS6Mlz9lW8RKd4r4KmvNgkyy2Yt21zec5bB7aJVuC9MV5\n"
"+6f20S/EHbbAi1YbOPtcPOaoIkdtXO5PuSwFy8HER5jYOQp+RUT5xC8HoS+jJCF9\n"
"5dCa9suSiw3vq0cNn91AIx+oU4lVrCNcVpX41aKsovk4wwuaOFinQqTN5k6xLNPq\n"
"M+yrZgECgYEA7bKgW1EgCRK5M/WZZTQbTSW7iWVZanrccotyxIkYzGpgmQy8AYKj\n"
"n2rpyeBXLwcBHPqdsWPVYSeEJJ9zbHxsBRxsX7MLvB5zRb0S05YVk0+x3YvDXhCy\n"
"42MHcPPjxWDvRh16j1h+IwRsIpatQrZnnKBXAGc/w4jVLZ2sV43imH8CgYEA7Lx8\n"
"PA/x9mSxBrjBIIpKQBlAcBzxT6z82AiDBfOG4Sf/P2fb/wNSRKVC/XeTh1Zczt1Z\n"
"ovPJdVe8qGsqEaI54Zrhp2shGfkvTTh4WwI3km8jdcEtjtHaoUBYFzmFd+Rrv8Uj\n"
"PWV5cfPmxbWG7GY9j6gudHgZE6iZLO1JtwPt5GECgYAfPvbzahOi/bIY0XUrp5Db\n"
"MFWZtxfs9l+aMxiQG1GGNYmjNNhV/n1RzHUVE4eCaBJOY+ds1SnMjqxBQDClFyn/\n"
"9f+NCPVG8l3G0hbyd204oyZHcELrT5ikaXUl9PmBDcAGYIOm6kQSiFdKqLH37hBq\n"
"t20YYXoxUwBq8aohDEa4MwKBgBVgl99cmT7krM+sk1P66OWM4jK9ilTljBd9/Ubm\n"
"TMG8OOJi4IzQofcs7TWyPJI2DD9p4ZRDa2e7OoAC3VOmUI+8yq+xjtWnmMviU4v0\n"
"UUxZ2NvjS9ffv1xcURgXy6Od7tTsWlhK94KAwdAMqlhiiyCT0U4XIjySNvLFoqhy\n"
"JGNBAoGAL/S8MY/eSrOwndafr/Oa+lHd7obuM9MuUsLzswhSJBZqnKAb+XGZCnEm\n"
"I8hTk2hQm68nrKpw8121rqvWejHmkUzKlZJ45ixokfj3TOktzcxb5/kGfvRnRuzG\n"
"nNwCNDQdC+lEfyiEoi8nuDEM0pR3emSWiUvI6QDDfER19psF62c=\n"
"-----END RSA PRIVATE KEY-----";
void setup() {
Serial.begin(9600);
setup_wifi();
// espClient.setInsecure();
espClient.setCACert(root_ca);
espClient.setCertificate(server_crt);
espClient.setPrivateKey(server_key);
client.setServer(mqtt_server, PORT);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
if (millis() - lastUpdateTime > updateInterval) { // 数据定时上报
sendJsonData();
lastUpdateTime = millis();
}
}
// MQTT 订阅回调函数,用于处理接收到的消息
void callback(char* topic, byte* payload, unsigned int length) {
String inputString;
for (int i = 0; i < length; i++) {
inputString += (char)payload[i];
}
Serial.println(inputString);
int dataBegin = inputString.indexOf("\"data\"");
if (dataBegin == -1) {
Serial.println(F("Missing 'data' field in JSON."));
return;
}
int builtInBegin = inputString.indexOf("\"builtIn\"", dataBegin);
if (builtInBegin == -1) {
Serial.println(F("Missing 'builtIn' field in 'data' object."));
return;
}
int valueBegin = inputString.indexOf(':', builtInBegin);
int valueEnd = inputString.indexOf('}', valueBegin);
if (valueBegin == -1 || valueEnd == -1) {
Serial.println(F("Invalid 'builtIn' value."));
return;
}
String builtInValueStr = inputString.substring(valueBegin + 1, valueEnd);
int builtInValue = builtInValueStr.toInt();
if (builtInValue == 0) {
Serial.println("close!");
} else {
Serial.println("open!");
}
}
void setup_wifi() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
// 重新连接 MQTT 服务器
void reconnect() {
while (!client.connected()) {
if (client.connect(ID)) {
client.subscribe(sub);
} else {
Serial.print(client.state());
delay(5000);
}
}
}
// 发送 JSON 格式的数据到 MQTT 服务器
void sendJsonData() {
sendJson["ID"] = ID;
String pubres;
serializeJson(sendJson, pubres);
int str_len = pubres.length() + 1;
char char_array[str_len];
pubres.toCharArray(char_array, str_len);
client.publish(pub, char_array);
}
Last modified: 12 一月 2024