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调试器
只要是同一个订阅,就可以互相发信息了
浙公网安备 33010602011771号