WaveshareCloud Wiki Help

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