ESP32 使用 Arduino 连接加密的 MQTT 服务器

背景

当前各大云服务商提供的MQTT服务(或者Websockets)基本都推荐使用TLS/SSL加密的方式连接,一般情况下ESP32所采用的Arduino MQTT 库是PubSubClient,当我们遇到需要加密连接的时候,可能会去寻找其他的支持SSL连接的库,但是使用下来发现无论从易用性、文档的完善性还是其他方面,都不如PubSubClient。因此,本文的重点就变成了如何使用PubSunClient连接加密的MQTT服务

准备工作

  1. ESP32开发板
  2. 电脑
  3. 路由器
  4. 支持TLS/SSL加密的MQTT服务器
  5. Arduino IDE / PlatformIO (VsCode 插件)

具体流程

首先我们先看一下一般情况下,使用PubSubClient连接非加密的MQTT服务器相关的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <WiFi.h>
#include <PubSubClient.h>

const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
const char* mqtt_server = "mqtt.example.com";
const int mqtt_port = 1883;
const char* mqtt_user = "your_USERNAME";
const char* mqtt_password = "your_PASSWORD";

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
}

void loop() {
if (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
Serial.println("Connected to MQTT server");
} else {
Serial.print("Failed to connect, state: ");
Serial.println(client.state());
delay(2000);
}
}
}
```

我们可以看到,主要分为几个部分,首先是连接WiFi,之后初始化MQTT服务器,最后是一个循环,用于保持连接状态。那么如果我们需要连接加密的MQTT服务器,我们需要做哪些修改呢?

首先,我们需要修改WiFi.begin函数,使其支持SSL/TLS加密,代码如下:

```cpp
// 首先需要引入WiFiClientSecure库
#include <WiFiClientSecure.h>
// 其次引入time库
#include <time.h>

// 初始化平台为你提供的公共CA证书
const char* mqtt_ca= \
"-----BEGIN CERTIFICATE-----\n" \
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" \
"................................................................\n" \
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" \
"-----END CERTIFICATE-----\n";


// 在初始化时先校准时间
configTime(0, 0, "ntp1.aliyun.com");

WiFiClientSecure wifiSecureClient;

// 加载CA证书
wifiSecureClient.setCACert(mqtt_ca);

接下来的步骤与之前的代码相同,我们可以看到,上面的代码中主要修改有两处,第一是需要校准时间,第二是需要加载证书。只需要简单的修改就可以实现加密连接了。以下是完整的加密连接代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>
#include <time.h>
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
const char* mqtt_server = "mqtt.example.com";
const int mqtt_port = 8883;
const char* mqtt_user = "your_USERNAME";
const char* mqtt_password = "your_PASSWORD";

WiFiClientSecure wifiSecureClient;

const char* mqtt_ca= \
"-----BEGIN CERTIFICATE-----\n" \
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" \
"................................................................\n" \
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" \
"-----END CERTIFICATE-----\n";

PubSubClient client(wifiSecureClient);

void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status()!= WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
// 加载CA证书
wifiSecureClient.setCACert(mqtt_ca);
// 校准时间
configTime(0, 0, "ntp1.aliyun.com");
}

void loop() {
if (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
Serial.println("Connected to MQTT server");
} else {
Serial.print("Failed to connect, state: ");
Serial.println(client.state());
delay(2000);
}
}
}

——Wicos 2025-05-28


ESP32 使用 Arduino 连接加密的 MQTT 服务器
https://www.wicos.me/jishu/1162/
作者
Wicos
发布于
2025年5月27日
许可协议