Arduino单片机MQTT的使用

这里我使用的是ESP32 C3  合宇的单片机开发板

我这里只有一个简单的应用,用开发板18根接一个继电器来控制开灯与关灯, 自带还有一个定时器开灯10分钟(600秒)关灯50分钟(3000)秒,通过wifi来校准北京时间

可以通过MQTT订阅来远程控制 开,关灯与查看状态等功能 

这里要添加两个库

#include <NTPClient.h>             网络校时
#include <PubSubClient.h>  MQTT连接库
 1. MQTT配置 54 // MQTT Broker Settings
    
 55 const char *mqtt_broker = "服务器地址";
 56 const char *mqtt_topic = "订阅标题";
 57 const char *mqtt_username = "用户名";
 58 const char *mqtt_password = "密码";
 59 const int mqtt_port = 1883;  //端口

2.   MQTT实例化

62 WiFiClient espClient;

63 PubSubClient mqtt_client(espClient);

3. MQTT 实例化配置参数

292   mqtt_client.setServer(mqtt_broker, mqtt_port);
293   mqtt_client.setKeepAlive(60);
294   mqtt_client.setCallback(mqttCallback); // Corrected callback function name
295   connectToMQTT();
4.子功能函数
connectToMQTT();  连接服务器
mqttCallback(); 根据订阅内容,执行相应的功能 (主要功能都在这里)

  1 //***************************************************************/ 
  2 // 
  3 //           -------------------------------------------
  4 //           board: ESP32C3 Dev Module
  5 //           Flash Mode: "DIO"
  6 //           -------------------------------------------
  7 //
  8 //***************************************************************/ 
  9         //help
 10         //马达开            马达开
 11         //马达关            马达关
 12         //马达运行时间      马达时间
 13         //马达开关次数      马达次数
 14         //当前时间          北京时间
 15 #include "Arduino.h"
 16 #include <WiFiUdp.h>
 17 #include <NTPClient.h>
 18 #include <WiFi.h>
 19 #include <PubSubClient.h>
 20 #include <WiFiClientSecure.h>
 21 //#include< WString.h>
 22 //#include "ESP32MQTTClient.h"
 23 #include <Ticker.h>
 24 // 定义LED引脚
 25 const int ledPin = 18;  //马达
 26 const int greenPin = 12; //wifi
 27 const int redPin = 10;   //mqtt
 28 const int second =30;     //定时频率
 29 // 新增变量:程序开始时间
 30 unsigned long programStartTime = 0;
 31 // 新增变量:亮灯次数
 32 unsigned long ledOnCount = 0;
 33 // 新增变量:累计亮灯时间
 34 unsigned long totalLedOnTime = 0;
 35 // 休眠时间
 36 const int night=20;
 37 const int morning=6;
 38 
 39 // 定义时间间隔(毫秒)
 40 const unsigned long intervalOn = 600000;
 41 const unsigned long intervalOff = 3000000;
 42 
 43 // 变量用于存储上次LED状态改变的时间
 44 unsigned long previousMillis = 0;
 45 // 变量用于跟踪LED当前状态
 46 bool ledState = LOW;
 47 //抽水马达状态
 48 const char *kai = "马达打开中";
 49 const char *guan = "马达关闭中";
 50 // WiFi Credentials
 51 const char *ssid = "GT";            // Replace with your WiFi name
 52 const char *password = "83333366";  // Replace with your WiFi password
 53 
 54 // MQTT Broker Settings
 55 const char *mqtt_broker = "服务器地址";
 56 const char *mqtt_topic = "订阅标题";
 57 const char *mqtt_username = "用户名";
 58 const char *mqtt_password = "密码";
 59 const int mqtt_port = 1883;  //端口
 60 
 61 
 62 WiFiClient  espClient;
 63 PubSubClient mqtt_client(espClient);
 64 
 65 // // Root CA Certificate  CA认证
 66 // const char* ca_cert = R"EOF(
 67 // -----BEGIN CERTIFICATE-----
 68 // MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
 69 // MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 70 // d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
 71 // QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
 72 // MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
 73 // b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
 74 // 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
 75 // CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
 76 // nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
 77 // 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
 78 // T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
 79 // gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
 80 // BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
 81 // TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
 82 // DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
 83 // hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
 84 // 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
 85 // PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
 86 // YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
 87 // CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
 88 // -----END CERTIFICATE-----
 89 // )EOF";
 90 
 91 //北京时间校准
 92 WiFiUDP ntpUDP;
 93 NTPClient timeClient(ntpUDP,"pool.ntp.org");
 94 String currentTime;
 95 String openTime;
 96 //发送抽水马达状态
 97 void sendMadaStatus(const char* str){
 98   if (mqtt_client.connected()){
 99   mqtt_client.publish(mqtt_topic, str);
100         timeClient.update();
101       Serial.println(timeClient.getFormattedTime());      
102   Serial.println(str);
103   }
104 }
105 
106 
107 
108 // 新增定时器回调函数
109 void timerCallback() {
110       timeClient.update();   
111       currentTime = timeClient.getFormattedTime();
112       String hours=currentTime.substring(0,2);
113       int hour=hours.toInt();
114   //判断是否处于休眠时间段
115   Serial.println(hour);
116   if( (hour >= night) || (hour < morning)) {
117     Serial.println("sleeping");
118     if (ledState == HIGH) {
119       // 关闭LED
120       ledState = LOW;
121       digitalWrite(ledPin, ledState);
122     }
123     // 这里可以添加休眠代码,例如ESP32的深度睡眠
124     //ESP.deepSleep(1 * 60 * 1000000); // 休眠30秒
125     return;
126   }
127   // 获取当前时间
128   Serial.println("aliving");
129   unsigned long currentMillis = millis();
130   if (ledState == LOW) {
131     // 如果LED当前是关闭状态,检查是否到了打开的时间
132     if (currentMillis - previousMillis >= intervalOff) {
133       // 记录上次状态改变的时间
134       previousMillis = currentMillis;
135       // 打开LED
136       ledState = HIGH;
137       digitalWrite(ledPin, ledState);
138       sendMadaStatus(kai);
139       timeClient.update();   
140       currentTime = timeClient.getFormattedTime();
141       sendMadaStatus(currentTime.c_str());
142 
143     }
144   } else {
145     // 如果LED当前是打开状态,检查是否到了关闭的时间
146     if (currentMillis - previousMillis >= intervalOn) {
147       // 增加亮灯次数
148       ledOnCount++;
149       // 累计亮灯时间
150       totalLedOnTime += intervalOn;
151       // 记录上次状态改变的时间
152       previousMillis = currentMillis;
153       // 关闭LED
154       ledState = LOW;
155       digitalWrite(ledPin, ledState);
156       sendMadaStatus(guan);
157       timeClient.update();   
158       currentTime = timeClient.getFormattedTime();
159       sendMadaStatus(currentTime.c_str());
160 
161     }
162   }
163 }
164 //长时间断后  再开启WIFI无法连接的问题
165 void connectToWiFi() {
166     WiFi.begin(ssid, password);
167     Serial.print("Connecting to WiFi");
168     int x=0;
169     while (WiFi.status() != WL_CONNECTED) {
170         x++;
171         delay(500);
172         Serial.print(".");
173         if(x>20){
174         WiFi.disconnect(true);
175         delay(1000);        
176         WiFi.mode(WIFI_OFF);
177         delay(1000);
178         x=0;
179         break;}
180     }
181     Serial.println("\nConnected to WiFi");
182     digitalWrite(greenPin, HIGH);
183 }
184 void connectToMQTT() {
185     while (!mqtt_client.connected()) {
186         if(  WiFi.status() != WL_CONNECTED){
187               digitalWrite(greenPin, LOW);
188               connectToWiFi();}
189         String client_id = "esp32-client-" + String(WiFi.macAddress());
190         Serial.printf("Connecting to MQTT Broker as %s.....\n", client_id.c_str());
191         if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
192             Serial.println("Connected to MQTT broker");
193                     timeClient.update();
194                     openTime=timeClient.getFormattedTime();
195             mqtt_client.subscribe(mqtt_topic);
196             mqtt_client.publish(mqtt_topic, openTime.c_str()); // Publish message upon successful connectionc_str()
197         } else {
198             Serial.print("Failed, rc=");
199             Serial.print(mqtt_client.state());
200             Serial.println(" try again in 5 seconds");
201             delay(5000);
202         }
203     }
204 }
205 void mqttCallback(char *mqtt_topic, byte *payload, unsigned int length) {
206     String  str;
207     Serial.print("Message received on mqtt_topic: ");
208     Serial.println(mqtt_topic);
209     Serial.print("Message: ");
210     for (unsigned int i = 0; i < length; i++) {
211         Serial.print((char) payload[i]);
212         str+=(char) payload[i];
213     }
214         //马达开
215         if(str=="马达开"){      
216       digitalWrite(ledPin, HIGH);
217       sendMadaStatus(kai);}
218         //马达关
219                 if(str=="马达关"){      
220       digitalWrite(ledPin, LOW);
221       sendMadaStatus(guan);}
222         //马达运行时间
223        if(str=="马达时间"){      
224       
225       sendMadaStatus(((String)totalLedOnTime).c_str());} 
226         //马达开关次数
227        if(str=="马达次数"){      
228       
229       sendMadaStatus(((String)ledOnCount).c_str());}
230         //当前时间
231        if(str=="北京时间"){ 
232                   
233               timeClient.update();   
234               currentTime = timeClient.getFormattedTime();
235               sendMadaStatus(currentTime.c_str());}
236         if(str=="重启")
237         {
238           esp_restart();
239         }
240         if(str=="状态"){
241           String maDa="";
242           if(ledState==LOW){maDa="马达关";}
243           else{maDa="马达开";}
244                         timeClient.update();   
245                         currentTime = timeClient.getFormattedTime();                        
246                         String maDaStatus="";
247                         maDaStatus="当前时间"+currentTime;
248                         //马达状态
249                         maDaStatus+=("\n 开机时间: "+openTime);
250                         maDaStatus+=("\n 马达状态: "+maDa);                        
251                         maDaStatus+=("\n 马达累计运行时间: "+(String)(totalLedOnTime/1000)+"");
252                         maDaStatus+=("\n 马达累计运行次数: "+ (String)ledOnCount);      
253                         sendMadaStatus(maDaStatus.c_str());}
254         if(str=="help"){
255            String help="help      马达开        马达关         马达时间          马达次数         北京时间          状态      重启   "  ;
256         sendMadaStatus(help.c_str());
257         }
258          
259     Serial.println("\n-----------------------");
260     Serial.println(str);
261 
262          
263 }
264 Ticker myTicker;
265 void setup() {  
266 
267   Serial.begin(115200);
268   Serial.print("开机成功");
269   // 记录程序开始时间
270   programStartTime = millis();
271   // 将LED引脚设置为输出模式
272   pinMode(ledPin, OUTPUT);
273   pinMode(greenPin, OUTPUT);
274   pinMode(redPin, OUTPUT);
275   ledState = HIGH;
276   digitalWrite(ledPin, HIGH);
277   // 假设使用Arduino的定时器库,这里简单模拟启动定时器
278   // 实际使用时需要根据具体定时器库修改
279   // 这里假设每1000ms调用一次定时器回调函数
280   myTicker.attach(second, timerCallback); // Call callbackFunction every 1 second
281   ///连接WIFI
282   connectToWiFi();
283       // Set Root CA certificate
284   //espClient.setCACert(ca_cert);
285     // 初始化NTP客户端
286   timeClient.begin();
287   // 设置时区偏移量,例如北京时间为 +8 小时,单位为秒
288   timeClient.setTimeOffset(28800);
289   timeClient.update();
290   openTime=timeClient.getFormattedTime();
291   ///mqtt连接
292   mqtt_client.setServer(mqtt_broker, mqtt_port);
293   mqtt_client.setKeepAlive(60);
294   mqtt_client.setCallback(mqttCallback); // Corrected callback function name
295   connectToMQTT();
296 
297 
298 }
299 
300 void loop() {
301   //连接WIFI
302   if(  WiFi.status() != WL_CONNECTED){
303     digitalWrite(greenPin, LOW);
304     connectToWiFi();}
305   //连接mqtt
306       if (!mqtt_client.connected()) {
307         connectToMQTT();
308     }
309     mqtt_client.loop();
310     
311     
312   // 可以添加打印时间的代码进行测试
313   // Serial.println(timeClient.getFormattedTime());
314   // 后台定时器处理逻辑已移至定时器回调函数
315   // 可以在这里添加其他任务
316 }

二.自架MQTT服务器(emqx开源项目)

     这里用的windows的 docker desktop软件,请自行安装

https://github.com/emqx/emqx 开源项目地址

https://docs.emqx.com/zh/       技术文档地址 

在DOS下运行  docker pull emqx/emqx-enterprise:5.9.0

        docker run -d --name emqx-enterprise -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx-enterprise:5.9.0

运行容器后,进入后台,添加用户名与密码后,,

给当前的用户添加认证

将添加的用户名,密码  加入到代码中

PC端可以用官方的工具    https://mqttx.app/zh/downloads

安卓端 可以用APP 应用市场就可以下                   MQTT调试器

只要是同一个订阅,就可以互相发信息了

posted @ 2025-05-13 14:45  clarklxr  阅读(149)  评论(0)    收藏  举报