下载MQTT库函数
-
菜单“项目”-“加载库”-“管理库”,搜索安装“PubSubClient”
通过菜单栏里"文件"→“示例”最下面找到PubSubClient查看是否下载成功
代码介绍
功能说明:
串口输入"ON"或者“OFF”到通过MQTT协议,以“LED”为主题发送到服务器,同时订阅“LED”,消息到服务器后就会立刻返回。根据返回的信息来控制NodeMCU板载LED灯。同时我们使用MQTT调试助手给“LED”主题发送“OFF”或者“ON”也可以实现板载LED的控制!
-
定义常用变量
#include <ESP8266WiFi.h> #include <PubSubClient.h> const char* ssid = "****";//连接的路由器的名字 const char* password = "****";//连接的路由器的密码 const char* mqtt_server = "****";//服务器的地址 const int port=****;//服务器端口号 const char* topic_name = "LED"; const char* client_id = "esp8266_0000001";
首先导入ESP8266和MQTT协议的库,填写我们所连接服务器的信息,不可以定义成String类型,arduino里String是一个对象!topic_name为订阅的主题,client_id是客户端的名称,尽量保持唯一,否则如果有相同的名称登录,就会把当前连接给顶替!
-
初始化:
//初始化WIFI void setup_wifi() {//自动连WIFI接入网络 delay(10); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("..."); } }
初始化WIFI连接,如果连接失败,延时0.5秒后继续尝试连接!
-
连接服务器
void reconnect() {//等待,直到连接上服务器 while (!client.connected()) {//如果没有连接上 if (client.connect(client_id)) {//接入时的用户名,尽量取一个很不常用的用户名 client.subscribe(topic_name);//接收外来的数据时的intopic Serial.println("connect success"); } else { Serial.print("failed, rc=");//连接失败 Serial.print(client.state());//重新连接 Serial.println(" try again in 5 seconds");//延时5秒后重新连接 delay(5000); } } }
连接服务器断开后会尝试从连,连接成功后发送接入的用户名,client.subscribe表示发送订阅的主题! 如果没有成功连接服务器,延时5秒后再次尝试连接。
-
消息回调
void callback(char* topic, byte* payload, unsigned int length) { String callMsg = ""; Serial.print("Message arrived ["); Serial.print(topic); // 打印主题信息 Serial.print("] "); for (int i = 0; i < length; i++) { callMsg += char(payload[i]); } Serial.println(callMsg); //如果返回ON关闭LED if(callMsg.equals("ON")){ digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level } //如果返回OFF关闭LED if(callMsg.equals("OFF")){ digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH }
}
当我们订阅的主题有消息传回时调用此方法,"topic":传来的是订阅的主题。 "payload"传递过来的内容是个二进制的流,所以可以任何的内容,当然上述代码中我们也可以将其转化为整数来用,另外还可以直接传递JSON格式的数据,这样能让数据更加可读。但在单片机的设备间通信还是以“小”为原则, 能传整数的时候绝不传字符串,这样可以大大减轻整体网络通信的负担同时也可以降低单片机运行的功耗。"length":传入的数据的长度!
定义callMsg接收返回的字符转换成String对象,然后使用equals()方法判断,如果"ON"打开板载LED,如果为"OFF"关闭板载LED。板载LED输出"HIGH"为熄灭注意 void callback(char* topic, byte* payload, unsigned int length)的参数是固定的,是一个方法接口除了方法名可改,类型与参数个数都不能错。
-
初始化函数
void setup() {//初始化程序,只运行一遍 Serial.begin(115200);//设置串口波特率(与烧写用波特率不是一个概念) setup_wifi();//自动连WIFI接入网络 client.setServer(mqtt_server, port);//端口号 client.setCallback(callback); //用于接收服务器接收的数据 }
程序初始化,初始化串口波特率:115200; 初始化WIFI和连接服务器。 setup函数程序只会执行一次,loop则会一直循环!
-
主循环:
void loop() {//主循环 String msg = "";//用于存放 reconnect();//确保连上服务器,否则一直等待。 client.loop();//MUC接收数据的主循环函数。 while (Serial.available() > 0) { msg += char(Serial.read()); delay(2); } int msglen = msg.length(); if (msglen > 0) { Serial.println(msg); char msgArr[msglen+1]; msg.toCharArray(msgArr,msglen + 1); client.publish(topic_name,msgArr); } }
接收串口的消息发送给服务器,然后回调函数再从服务器接收到返回的消息选择打开还是关闭LED!程序中注意String类型,它和直接""双引号下的变量有区别的!
完整代码
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* ssid = "XXX";//连接的路由器的名字
const char* password = "XXXXX";//连接的路由器的密码
const char* mqtt_server = "XXXX";//服务器的地址
const int port=1883;//服务器端口号
const char* topic_name = "LED";//订阅的主题
const char* client_id = "esp8266_0000001";//尽量保持唯一,相同的id连接会被替代
WiFiClient espClient;
PubSubClient client(espClient);
//初始化WIFI
void setup_wifi() {//自动连WIFI接入网络
delay(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("...");
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String callMsg = "";
Serial.print("Message arrived [");
Serial.print(topic); // 打印主题信息
Serial.print("] ");
for (int i = 0; i < length; i++) {
callMsg += char(payload[i]);
}
Serial.println(callMsg);
//如果返回ON关闭LED
if(callMsg.equals("ON")){
digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level
}
//如果返回OFF关闭LED
if(callMsg.equals("OFF")){
digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH
}
}
void reconnect() {//等待,直到连接上服务器
while (!client.connected()) {//如果没有连接上
if (client.connect(client_id)) {//接入时的用户名,尽量取一个很不常用的用户名
client.subscribe(topic_name);//接收外来的数据时的intopic
Serial.println("connect success");
} else {
Serial.print("failed, rc=");//连接失败
Serial.print(client.state());//重新连接
Serial.println(" try again in 5 seconds");//延时5秒后重新连接
delay(5000);
}
}
}
void setup() {//初始化程序,只运行一遍
Serial.begin(115200);//设置串口波特率(与烧写用波特率不是一个概念)
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
digitalWrite(LED_BUILTIN, HIGH);
setup_wifi();//自动连WIFI接入网络
client.setServer(mqtt_server, port);//端口号
client.setCallback(callback); //用于接收服务器接收的数据
}
void loop() {//主循环
String msg = "";//用于存放
reconnect();//确保连上服务器,否则一直等待。
client.loop();//MUC接收数据的主循环函数。
while (Serial.available() > 0)
{
msg += char(Serial.read());
delay(2);
}
int msglen = msg.length();
if (msglen > 0)
{
Serial.println(msg);
char msgArr[msglen+1];
msg.toCharArray(msgArr,msglen + 1);
client.publish(topic_name,msgArr);
}
}
上传程序到我们的开发板成功后打开串口调试!
使用MQTT测试助手
-
串口测试:
通过串口输入发送“ON”和“OFF”查看LED的变化,也可以使用MQTT调试助手测试,在google浏览器里搜索MQTTlens进行安装!
-
连接服务器
-
给"LED"主题发送消息
Publish里填入‘LED’主题,Message 填写要发送的消息