简介
本文主要介绍如何使用 ESP8266 连接MQTT服务器,利用 PubSubClient
库,实现客户端与 MQTT 服务器的连接、订阅、收发消息等功能。服务器使用EMQX为例。部分代码使用 PubSubClient
库自带的示例。
连接到MQTT服务器分为TCP方式连接和TLS/SSL方式连接,使用EMQX的公共服务器的话是TCP方式连接,使用EMQX的私有服务器为TLS/SSL方式连接。TCP和TLS/SSL连接的区别在于定义espClient的方式不同,连接服务器的端口不同,以及TLS/SSL需要填写服务器指纹,并使用espClient.setFingerprint(fingerprint);
设置指纹
EMQX私有服务器链接,使用说明,私有服务器有一定的免费额度,每月1百万连接分钟数(大约23个设备持续在线连接1个月)和1G流量。
首先先在Arduino IDE的 管理库 中添加 PubSubClient
库
常用函数
WiFiClient espClient; //TCP连接
WiFiClientSecure espClient; //TLS/SSL连接
PubSubClient client(espClient); //定义client
espClient.setFingerprint(fingerprint); //TLS/SSL连接,设置指纹
client.setServer(mqtt_server, mqtt_port); //设置服务器地址和端口
client.setCallback(callback); //设置接收消息的函数
client.connect(clientId.c_str()); //连接服务器,不使用用户名和密码
client.connect(clientId.c_str() , mqtt_name , mqtt_password); //连接服务器,使用用户名和密码
client.connected(); //返回是否连接成功,0为失败,1为成功
client.state(); //返回连接状态码
client.publish(topic, "connected"); //向主题发布消息,可以不用订阅主题
client.subscribe(topic); //订阅主题,用于接收消息,qos默认为0
client.subscribe(topic,qos); //订阅主题,用于接收消息,并填写qos
client.unsubscribe(topic); //取消订阅
client.loop();
头文件
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
定义基本信息
const char* ssid = ""; //WiFi名
const char* password = ""; //WiFi密码
const char* mqtt_server = ""; //MQTT服务器地址
const int mqtt_port = 1883; //服务器连接端口
const char* mqtt_name = ""; //MQTT连接用户名(可选)
const char* mqtt_password = ""; //MQTT连接密码(可选)
const char* topic=""; //订阅、发布的主题
MQTT连接用户名和密码都是可选的,具体要根据MQTT服务器。一般来说,使用TCP连接服务器,端口为1883;使用TLS/SSL连接服务器,端口为8883。
如果使用 EMQX的公共服务器,使用TCP连接,服务器地址为broker.emqx.io
,端口为1883,连接用户名为emqx
,密码为public
,也可以不填。
如果使用私有服务器,使用TLS/SSL连接,服务器地址根据控制台具体信息,端口为8883,用户名和密码自己在控制台里定义。
定义 espClient
和 client
。如果使用TCP连接,则按以下定义:
WiFiClient espClient;
PubSubClient client(espClient);
TLS/SSL连接
如果使用TLS/SSL连接,则按以下连接:
设置服务器和证书:
// WiFi和MQTT客户端初始化
BearSSL::WiFiClientSecure espClient;
PubSubClient mqtt_client(espClient);
// NTP服务器设置
const char *ntp_server = "pool.ntp.org"; // 默认NTP服务器
// const char* ntp_server = "cn.pool.ntp.org"; // 为国内推荐的NTP服务器
const long gmt_offset_sec = 0; // 以秒为单位的GMT时差(根据时区进行调整)
const int daylight_offset_sec = 0; // 夏令时偏移量(秒)
// MQTT代理的SSL证书
// 如果使用公共服务器: broker.emqx.io
的DigiCert Global Root G2
static const char ca_cert[]
PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----
)EOF";
// 如果使用EMQX的Serverless服务
/*
static const char ca_cert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----
)EOF";
*/
setup
函数
如果TLS/SSL连接,则需要使用 Client.setFingerprint(fingerprint);
设置指纹
void setup() {
Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
pinMode(BUILTIN_LED, OUTPUT);
Serial.begin(115200);
setup_wifi(); //连接WiFi
//syncTime(); // 如果使用TLS/SSL连接,需要添加此行,X.509验证需要同步时间
//espClient.setFingerprint(fingerprint);
client.setServer(mqtt_server, mqtt_port); //设置服务器地址和端口
client.setCallback(callback); //设置接收消息的函数
}
/*
void syncTime() {
configTime(gmt_offset_sec, daylight_offset_sec, ntp_server);
Serial.print("Waiting for NTP time sync: ");
while (time(nullptr) < 8 * 3600 * 2) {
delay(1000);
Serial.print(".");
}
Serial.println("Time synchronized");
}
*/
建立WiFi连接
void setup_wifi() {
digitalWrite(BUILTIN_LED, LOW);
delay(10);
// We start by connecting to a WiFi network
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(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
digitalWrite(BUILTIN_LED, HIGH);
}
建立MQTT连接
建立MQTT连接以及断开后的重连,这里需要定义设备名, 设备名可以自己定义,也可以使用XX-随机数,XX-IP地址等,例如ESP8266-1898,ESP8266-123.456.7.891
如果存在相同的设备ID,那么所有拥有相同设备ID的设备将会不断的断开重连。所以建议在设备ID后添加上IP地址。
前面提过,连接用户名和密码可填可不填,如果使用用户名和密码,则使用 client.connect(clientId.c_str() , mqtt_name , mqtt_password)
来连接MQTT服务器,如果不使用用户名和密码,则使用 client.connect(clientId.c_str())
来连接。
void reconnect() {
//循环直到回连成功
//BearSSL::X509List serverTrustedCA(ca_cert);
//如果使用TLS/SSL连接,需要添加这两句
//espClient.setTrustAnchors(&serverTrustedCA);
while (!client.connected())
{
Serial.print("Attempting MQTT connection...");
String clientId = "ESP8266-"; //设备名
// clientId += String(random(0xffff), HEX); 使用XX-随机数
clientId += WiFi.localIP().toString().c_str(); //XX-IP地址
// 尝试连接
if (client.connect(clientId.c_str() , mqtt_name , mqtt_password)) //client.connect(clientId.c_str())
{
Serial.println("connected"); //连接成功
client.publish(topic, "connected"); //连接成功后,向主题发布消息,也可以不发布
client.subscribe(topic); //订阅主题
}
else
{
char err_buf[128];
espClient.getLastSSLError(err_buf, sizeof(err_buf));
Serial.print("failed, rc="); //连接失败,并打印状态码
Serial.print(client.state());
Serial.print(" SSL error: ");
Serial.println(err_buf);
Serial.println(" try again in 5 seconds");
delay(5000); //5秒后再次尝试连接
}
}
}
PubSubClient
库中 PubSubClient.h
对于状态码的定义
// Possible values for client.state()
#define MQTT_CONNECTION_TIMEOUT -4
#define MQTT_CONNECTION_LOST -3
#define MQTT_CONNECT_FAILED -2
#define MQTT_DISCONNECTED -1
#define MQTT_CONNECTED 0
#define MQTT_CONNECT_BAD_PROTOCOL 1
#define MQTT_CONNECT_BAD_CLIENT_ID 2
#define MQTT_CONNECT_UNAVAILABLE 3
#define MQTT_CONNECT_BAD_CREDENTIALS 4
#define MQTT_CONNECT_UNAUTHORIZED 5
接收订阅的消息
void callback(char* topic, byte* payload, unsigned int length) //主题,消息,消息长度
{
Serial.print("Message arrived [");
Serial.print(topic); //打印主题
Serial.print("] ");
char msg[length];
for (int i = 0; i < length; i++)
msg[i]=(char)payload[i]; //将消息转存到msg中
snprintf (msg, length+1, msg);
Serial.println(msg); //打印消息
if (!strcmp(msg, "on")) digitalWrite(BUILTIN_LED, LOW); //如果接收到on,则将esp8266板载的led点亮,注意,将BUILTIN_LED置为低时,LED会被点亮
if (!strcmp(msg, "off")) digitalWrite(BUILTIN_LED, HIGH); //如果接收到on,则将led熄灭,注意,将BUILTIN_LED置为高时,LED会被熄灭
}
loop函数
void loop()
{
if (!client.connected())
//如果断连,则进行重连
{
reconnect();
}
client.loop();
unsigned long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
++value;
snprintf (msg, MSG_BUFFER_SIZE, "hello world #%ld", value);
Serial.print("Publish message: ");
Serial.println(msg);
client.publish(topic, msg);
//每2秒发送一次消息
}
}
完整代码示例
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* ssid = ""; //WiFi名
const char* password = ""; //WiFi密码
const char* mqtt_server = "broker.emqx.io"; //MQTT服务器地址
const int mqtt_port = 1883; //服务器连接端口
const char* mqtt_name = "emqx"; //MQTT连接用户名(可选)
const char* mqtt_password = "public"; //MQTT连接密码(可选)
const char* topic="testtopic"; //订阅、发布的主题
/*
// NTP服务器设置
const char *ntp_server = "pool.ntp.org"; // 默认NTP服务器
// const char* ntp_server = "cn.pool.ntp.org"; // 为国内推荐的NTP服务器
const long gmt_offset_sec = 0; // 以秒为单位的GMT时差(根据时区进行调整)
const int daylight_offset_sec = 0; // 夏令时偏移量(秒)
// WiFi和MQTT客户端初始化
WiFiClientSecure espClient;
PubSubClient client(espClient);
// MQTT代理的SSL证书
// 如果使用公共服务器: broker.emqx.io的DigiCert Global Root G2
static const char ca_cert[]
PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----
)EOF";*/
// 如果使用EMQX的Serverless服务
/*
static const char ca_cert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----
)EOF";
*/
WiFiClient espClient; //如果使用TLS/SSL连接,需要注释掉这两行
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;
void setup() {
Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
pinMode(BUILTIN_LED, OUTPUT);
Serial.begin(115200);
setup_wifi(); //连接WiFi
//syncTime(); // 如果使用TLS/SSL连接,需要添加此行,X.509验证需要同步时间
client.setServer(mqtt_server, mqtt_port); //设置服务器地址和端口
client.setCallback(callback); //设置接收消息的函数
}
/*
void syncTime() {
configTime(gmt_offset_sec, daylight_offset_sec, ntp_server);
Serial.print("Waiting for NTP time sync: ");
while (time(nullptr) < 8 * 3600 * 2) {
delay(1000);
Serial.print(".");
}
Serial.println("Time synchronized");
}
*/
void setup_wifi() {
digitalWrite(BUILTIN_LED, LOW);
delay(10);
// We start by connecting to a WiFi network
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(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
digitalWrite(BUILTIN_LED, HIGH);
}
void reconnect() {
//循环直到回连成功
//BearSSL::X509List serverTrustedCA(ca_cert); //如果使用TLS/SSL连接,需要添加这两句
//espClient.setTrustAnchors(&serverTrustedCA);
while (!client.connected())
{
Serial.print("Attempting MQTT connection...");
String clientId = "ESP8266-"; //设备名
// clientId += String(random(0xffff), HEX); 使用XX-随机数
clientId += WiFi.localIP().toString().c_str(); //XX-IP地址
// 尝试连接
if (client.connect(clientId.c_str() , mqtt_name , mqtt_password)) //client.connect(clientId.c_str())
{
Serial.println("connected"); //连接成功
client.publish(topic, "connected"); //连接成功后,向主题发布消息,也可以不发布
client.subscribe(topic); //订阅主题
}
else
{
char err_buf[128];
espClient.getLastSSLError(err_buf, sizeof(err_buf));
Serial.print("failed, rc="); //连接失败,并打印状态码
Serial.print(client.state());
Serial.print(" SSL error: ");
Serial.println(err_buf);
Serial.println(" try again in 5 seconds");
delay(5000); //5秒后再次尝试连接
}
}
}
void callback(char* topic, byte* payload, unsigned int length) //主题,消息,消息长度
{
Serial.print("Message arrived [");
Serial.print(topic); //打印主题
Serial.print("] ");
char msg[length];
for (int i = 0; i < length; i++)
msg[i]=(char)payload[i]; //将消息转存到msg中
snprintf (msg, length+1, msg);
Serial.println(msg); //打印消息
if (!strcmp(msg, "on")) digitalWrite(BUILTIN_LED, LOW); //如果接收到on,则将esp8266板载的led点亮,注意,将BUILTIN_LED置为低时,LED会被点亮
if (!strcmp(msg, "off")) digitalWrite(BUILTIN_LED, HIGH); //如果接收到on,则将led熄灭,注意,将BUILTIN_LED置为高时,LED会被熄灭
}
void loop()
{
if (!client.connected()) //如果断连,则进行重连
{
reconnect();
}
client.loop();
unsigned long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
++value;
snprintf (msg, MSG_BUFFER_SIZE, "hello world #%ld", value);
Serial.print("Publish message: ");
Serial.println(msg);
client.publish(topic, msg); //每2秒发送一次消息
}
}
Comments | 1 条评论
博主 Mark Khan
该评论为私密评论