简介
本文环境为:
单片机: ESP32
通讯协议: 串口通讯, MQTT, WIFI
所用库说明:
1 WiFi.h
:这是一个ESP32开发板的WiFi库,用于连接WiFi网络。
2 PubSubClient.h
:这是一个MQTT客户端库,用于连接MQTT代理并发布/订阅主题。
3 ArduinoJson.h
:这是一个处理JSON数据的库,可以在ESP32上方便地解析和生成JSON数据。
4 Ticker.h
:这是一个用于ESP32中的软件定时器库,可以在ESP32上运行回调函数。
实现功能:
●连接指定WIFI
●连接指定MQTT服务器
●发布唯一主题
●订阅唯一主题
●发布消息
●接受订阅消息
●收到主题"device/dev/1"的"ON"消息, 将LED2和D5设为高电平(开)
●收到主题"device/dev/1"的"OFF"消息, 将LED2设为低电平(关)
●(dev) 第一次启动必须将WIFI设置为特定名称和密码, 让ESP32连接WIFI, 然后通过MQTT设置自定义WIFI和密码, 一共两个WIFI和密码, 第一个可自定义, 第二个不可自定义, 以防丢失WIFI密码
●注: esp32本身可以当做WIFI去连接并控制
代码示例:
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Ticker.h>
const int ledPin = 5; // D5针脚对应的数字编号
StaticJsonDocument<200> sensor_json; // JSON对象
String realmsg = ""; // 发布消息载体
int LED = 2;
// 设置wifi接入信息(请根据您的WiFi信息进行修改)
// const char* ssid = "realme";
// const char* password = "12345678";
const char* mqttServer = "api.shuxinxin.top";//本机ip地址
//发布的消息字段
typedef struct {
int msg1;
int msg2;
int msg3;
} msg;
int count = 0; //发布消息间隔
// 如以上MQTT服务器无法正常连接,请前往以下页面寻找解决方案
// http://www.taichi-maker.com/public-mqtt-broker/
//------------------全局变量定义-----------------
msg mymsg = {123, 45, 6}; //定义消息结构体
Ticker ticker;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
//------------------全局变量定义-----------------
void tickerCount()
{ //Ticker回调函数
count++;
//数据测试
sensor_json["msg1"] = 12;
sensor_json["msg2"] = 21;
sensor_json["msg3"] = 98;
serializeJson(sensor_json, realmsg);
}
void pubmsg( const String &topicString, const String &messageString)
{
char publishTopic[topicString.length() + 1];
strcpy(publishTopic, topicString.c_str());
char publishMsg[messageString.length() + 1];
strcpy(publishMsg, messageString.c_str());
// 实现ESP8266向主题发布信息
if (mqttClient.publish(publishTopic, publishMsg))
{
Serial.println("Publish Topic:"); Serial.println(publishTopic);
Serial.println("Publish message:"); Serial.println(publishMsg);
}
else
{
Serial.println("Message Publish Failed.");
}
}
void setup()
{
pinMode(LED, OUTPUT); // 设置板上LED引脚为输出模式
pinMode(ledPin, OUTPUT); // 将D5针脚配置为输出模式
digitalWrite(LED, LOW); // 启动后关闭板上LED
Serial.begin(9600); // 启动串口通讯
// Ticker定时对象
ticker.attach(2, tickerCount); //每过2s调用其回调函数
//设置ESP8266工作模式为无线终端模式
// WiFi.mode(WIFI_STA);
// 连接WiFi
connectWifi();
// 设置MQTT服务器和端口号
mqttClient.setServer(mqttServer, 1883);
mqttClient.setCallback(receiveCallback);
// 连接MQTT服务器
connectMQTTserver();
}
void loop()
{
if (mqttClient.connected())
{ // 如果开发板成功连接服务器
if (count >= 2)
{
pubmsg("device/date", realmsg);
realmsg = "";
count = 0;
}
// mqttClient.loop(); // 处理信息以及心跳
}
else
{ // 如果开发板未能成功连接服务器
connectMQTTserver(); // 则尝试连接服务器
}
mqttClient.loop(); // 处理信息以及心跳
}
// 连接MQTT服务器并订阅信息
void connectMQTTserver()
{
// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)
// String clientId = "esp8266-" + WiFi.macAddress();
String clientId = "ESP32Client";
// 连接MQTT服务器
if (mqttClient.connect(clientId.c_str()))
{
Serial.println("MQTT Server Connected.");
Serial.println("Server Address:");
Serial.println(mqttServer);
Serial.println("ClientId: ");
Serial.println(clientId);
subscribeTopic(); // 订阅指定主题
}
else
{
Serial.print("MQTT Server Connect Failed. Client State:");
Serial.println(mqttClient.state());
delay(5000);
}
}
// 收到信息后的回调函数
void receiveCallback(char* topic, byte* payload, unsigned int length)
{
Serial.print("Message Received [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
Serial.println("");
Serial.print("Message Length(Bytes) ");
Serial.println(length);
int temp = 0;
while (*topic)
{
temp++;
topic++;
}
Serial.println("主题长度:");
Serial.println(temp);
if (temp > 11)
{
if ((char)topic[11] == '1')
{
if ((char)payload[0] == 'O' && (char)payload[1] == 'F')
{ // 如果收到的信息以“1”为开始
Serial.println("关灯");
digitalWrite(LED, LOW); // 则熄灭LED。
}
else
{
Serial.println("开灯");
digitalWrite(LED, HIGH); // 否则亮LED。
digitalWrite(ledPin, HIGH); // 输出高电平,点亮LED
}
}
}
}
// 订阅指定主题
void subscribeTopic()
{
// 通过串口监视器输出是否成功订阅主题1以及订阅的主题1名称
if (mqttClient.subscribe("device/dev/#"))
{
Serial.println("Subscrib Topic:");
Serial.println("device/action");
}
else
{
Serial.print("Subscribe Fail...");
}
}
// ESP8266连接wifi
void connectWifi()
{
WiFi.begin("Wokwi-GUEST", "", 6);
while (WiFi.status() != WL_CONNECTED)
{
delay(100);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi Connected!");
Serial.println("");
}