網頁javascript
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>ESP8266 配置信息</title> <link href="css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div style="text-align:center;"> <h1 style="background-color:rgba(155,255,30,0.75)">歡迎使用</h1> <div class="starter-template";clear:both;text-align:center;"> <h3 style="background-color:rgba(255,10,10,0.75);color:#ffffff;">1板載LED控制</h3> <button onclick='setPinValue("on")' >點亮</button> <button onclick='setPinValue("off")' >熄滅</button> <p style="color:#40B3DF;">LED狀態: <span id="txtState"></span></p> </div> <div class="starter-template"> <h3 style="background-color:rgba(255,10,10,0.75);color:#ffffff;">2選擇WIFI鏈接方式:</h3> <div style="color:#40B3DF;"> <p>WIFI鏈接狀態: <span id="wifiState"></span></p> <div/> <hr/> <h4><2.1>普通WIFI上網(家庭)</h4> <form action=""> WIFI名稱: <input type="text" id="wifiname" /> </form> <form action=""> WIFI密碼: <input type="text" id="wifipwd" /> </form> <br/> <button onclick='setWifi(wifiname.value,wifipwd.value)' >鏈接</button> <h4><2.2>網頁認證上網(學校和商場)</h4> <form action=""> WIFI名稱: <input type="text" id="wifi_wname" /> </form> <form action=""> 登錄網址: <input type="text" id="wifi_wip" /> </form> <form action=""> <form action=""> 上網密鑰: <input type="text" id="wifi_postdata" /> </form> <p style="color:#01a1ff;">(上網密鑰 = 帳號(學號)+密碼+其餘信息)<p/> <button onclick='setWifi_wangye(wifi_wname.value,wifi_wip.value,wifi_postdata.value)' >鏈接</button> <br/> <hr/> </div> </div> <script src="js/jquery.min.js"></script> <script src="js/bootstrap.min.js"></script> <div> <button onclick='' >如何一鍵獲取上網密鑰?</button> </div> <script type="text/javascript"> function setPinValue(value) { alert("按鍵點擊!"); var xmlhttp; if (value.length==0) { document.getElementById("txtState").innerHTML="請點擊正確按鍵!"; return; } if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行代碼 xmlhttp=new XMLHttpRequest(); } else { // IE6, IE5 瀏覽器執行代碼 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState==4 && xmlhttp.status==200){ //alert(xmlhttp.responseText); //alert("操做成功"); document.getElementById("txtState").innerHTML = xmlhttp.responseText; } } var requestString = "/pin?a=" + value + "&pin=2"; xmlhttp.open("GET", requestString, true); xmlhttp.send(null); } function setWifi(name,pwd) { alert("按鍵點擊!"); var xmlhttp; if (name.length==0) { document.getElementById("wifiState").innerHTML="請輸入WIFI信息!"; return; } if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行代碼 xmlhttp=new XMLHttpRequest(); } else { // IE6, IE5 瀏覽器執行代碼 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState==4 && xmlhttp.status==200){ //alert(xmlhttp.responseText); //alert("操做成功"); document.getElementById("wifiState").innerHTML = xmlhttp.responseText; } } var requestString = "/wifi?config=on" + "&name="+name+"&pwd="+pwd; xmlhttp.open("GET", requestString, true); xmlhttp.send(null); } function setWifi_wangye(wifi_wname,wifi_wip,wifi_postdata) { alert("按鍵點擊!"); var xmlhttp; if (wifi_wname.length==0||wifi_wip.length==0||wifi_postdata.length==0) { document.getElementById("wifiState").innerHTML="請輸入網頁認證信息!"; return; } //for(var i=0;i<wifi_postdata.length;i++) //{ //if(wifi_postdata[i]=="&")wifi_postdata[i]="-"; //} if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行代碼 xmlhttp=new XMLHttpRequest(); } else { // IE6, IE5 瀏覽器執行代碼 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState==4 && xmlhttp.status==200){ //alert(xmlhttp.responseText); //alert("操做成功"); document.getElementById("wifiState").innerHTML = xmlhttp.responseText; } } var requestString = "/wifi_wangye?config=on" + "&wifi_wname="+wifi_wname+"&wifi_wpwd"+""+"&wifi_wip="+wifi_wip+"&wifi_postdata="+wifi_postdata; xmlhttp.open("GET", requestString, true); xmlhttp.send(null); } </script> </body> </html>
程序代碼php
/* 1 上電從rom讀取上次WIFI地址 成功-1網頁交互 2MQTT通訊 失敗-進入網頁模式,等待新的密碼 2 添加上電檢測重連wifi, 若是是普通直連,若是是網頁認證,直連+網頁請求 */ //------是否開啓打印----------------- #define Use_Serial Serial //-----------------------------A-1 庫引用開始-----------------// #include <string.h> #include <math.h> // 數學工具庫 #include <EEPROM.h>// eeprom 存儲庫 // WIFI庫 #include <ESP8266WiFi.h> //-------客戶端--------- #include <ESP8266HTTPClient.h> //---------服務器--------- #include <ESP8266WebServer.h> #include <FS.h> //Mqtt #include "Adafruit_MQTT.h" #include "Adafruit_MQTT_Client.h" //ESP獲取自身ID #ifdef ESP8266 extern "C" { #include "user_interface.h" //含有system_get_chip_id()的庫 } #endif //-----------------------------A-1 庫引用結束-----------------// //-----------------------------A-2 變量聲明開始-----------------// int PIN_Led = D4; bool PIN_Led_State=0; ESP8266WebServer server ( 80 ); //儲存SN號 String SN; /*----------------WIFI帳號和密碼--------------*/ char ssid[50] = ""; // Enter SSID here char password[50] = ""; //Enter Password here #define DEFAULT_STASSID "lovelamp" #define DEFAULT_STAPSW "lovelamp" // 用於存上次的WIFI和密碼 #define MAGIC_NUMBER 0xAA struct config_type { char stassid[50]; char stapsw[50]; uint8_t magic; }; config_type config_wifi; //------mqtt頭定義----------------- #define AIO_SERVER "www.dongvdong.top" //mqtt服務器 #define AIO_SERVERPORT 1883 //端口 #define AIO_USERNAME "" #define AIO_KEY "" WiFiClient mqttclient; //------mqtt通訊----------------- Adafruit_MQTT_Client mqtt(&mqttclient, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_USERNAME, AIO_KEY); Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/test", MQTT_QOS_1); //--------------HTTP請求------------------ struct http_request { String Referer; char host[20]; int httpPort=80; String host_ur ; String usr_name;//帳號 String usr_pwd;//密碼 String postDate; }; String http_html; //-----------------------------A-2 變量聲明結束-----------------// //-----------------------------A-3 函數聲明開始-----------------// void wifi_Init(); void saveConfig(); void loadConfig(); int hdulogin(struct http_request ruqest) ; void http_wifi_xidian(); String getContentType(String filename); void handleNotFound(); void handleMain(); void handlePin(); void handleWifi(); void http_jiexi(http_request ruqest); void handleWifi_wangye(); void handleTest(); void MQTT_connect(); void onoffcallback(char *data, uint16_t len) ; //---------------------------A-3 函數聲明結束------------------------// //-----------------------------A-3 函數-----------------// //3-1管腳初始化 void get_espid(){ SN = (String )system_get_chip_id(); Use_Serial.println(SN); } void LED_Int(){ pinMode(D4, OUTPUT); } //3-2WIFI初始化 void wifi_Init(){ Use_Serial.println("Connecting to "); Use_Serial.println(config_wifi.stassid); WiFi.begin(config_wifi.stassid, config_wifi.stapsw); int retries=3; while (WiFi.status() != WL_CONNECTED) { server.handleClient(); // retries--; // if (retries == 0) { // Use_Serial.println("WIFI connect 3 times fail!"); // return; // } ESP.wdtFeed(); delay(500); Use_Serial.print("."); PIN_Led_State = !PIN_Led_State; digitalWrite(PIN_Led, PIN_Led_State); } Use_Serial.println("--------------WIFI CONNECT!------------- "); Use_Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str()); Use_Serial.printf("PSW:%s\r\n", WiFi.psk().c_str()); Use_Serial.println("---------------------------------------- "); } /* *3-/2 保存參數到EEPROM */ void saveConfig() { Serial.println("Save config!"); Serial.print("stassid:"); Serial.println(config_wifi.stassid); Serial.print("stapsw:"); Serial.println(config_wifi.stapsw); EEPROM.begin(1024); uint8_t *p = (uint8_t*)(&config_wifi); for (int i = 0; i < sizeof(config_wifi); i++) { EEPROM.write(i, *(p + i)); } EEPROM.commit(); } /* * 從EEPROM加載參數 */ void loadConfig() { EEPROM.begin(1024); uint8_t *p = (uint8_t*)(&config_wifi); for (int i = 0; i < sizeof(config_wifi); i++) { *(p + i) = EEPROM.read(i); } EEPROM.commit(); //出廠自帶 if (config_wifi.magic != MAGIC_NUMBER) { strcpy(config_wifi.stassid, DEFAULT_STASSID); strcpy(config_wifi.stapsw, DEFAULT_STAPSW); config_wifi.magic = MAGIC_NUMBER; saveConfig(); Serial.println("Restore config!"); } Serial.println(" "); Serial.println("-----Read config-----"); Serial.print("stassid:"); Serial.println(config_wifi.stassid); Serial.print("stapsw:"); Serial.println(config_wifi.stapsw); Serial.println("-------------------"); // ssid=String(config.stassid); // password=String(config.stapsw); } //3-3ESP8266創建無線熱點 void SET_AP(){ // 設置內網 IPAddress softLocal(192,168,4,1); // 1 設置內網WIFI IP地址 IPAddress softGateway(192,168,4,1); IPAddress softSubnet(255,255,255,0); WiFi.softAPConfig(softLocal, softGateway, softSubnet); String apName = ("ESP8266_"+(String)ESP.getChipId()); // 2 設置WIFI名稱 const char *softAPName = apName.c_str(); WiFi.softAP(softAPName, "admin"); // 3建立wifi 名稱 +密碼 adminadmin Use_Serial.print("softAPName: "); // 5輸出WIFI 名稱 Use_Serial.println(apName); IPAddress myIP = WiFi.softAPIP(); // 4輸出建立的WIFI IP地址 Use_Serial.print("AP IP address: "); Use_Serial.println(myIP); } //3-4ESP創建網頁服務器 void Server_int(){ server.on ("/", handleMain); // 綁定‘/’地址到handleMain方法處理 ---- 返回主頁面 一鍵配網頁面 server.on ("/pin", HTTP_GET, handlePin); // 綁定‘/pin’地址到handlePin方法處理 ---- 開關燈請求 server.on ("/wifi", HTTP_GET, handleWifi); // 綁定‘/wifi’地址到handlePWIFI方法處理 --- 從新配網請求 server.on ("/wifi_wangye", HTTP_GET, handleWifi_wangye); server.on ("/test", HTTP_GET, handleTest); server.onNotFound ( handleNotFound ); // NotFound處理 server.begin(); Use_Serial.println ( "HTTP server started" ); } //3-5-1 網頁服務器主頁 void handleMain() { /* 返回信息給瀏覽器(狀態碼,Content-type, 內容) * 這裏是訪問當前設備ip直接返回一個String */ Serial.print("handleMain"); File file = SPIFFS.open("/index.html", "r"); size_t sent = server.streamFile(file, "text/html"); file.close(); return; } //3-5-2 網頁控制引腳 /* 引腳更改處理 * 訪問地址爲htp://192.162.xxx.xxx/pin?a=XXX的時候根據a的值來進行對應的處理 */ void handlePin() { if(server.hasArg("a")) { // 請求中是否包含有a的參數 String action = server.arg("a"); // 得到a參數的值 if(action == "on") { // a=on digitalWrite(2, LOW); // 點亮8266上的藍色led,led是低電平驅動,須要拉低才能亮 server.send ( 200, "text/html", "Pin 2 has turn on"); return; // 返回數據 } else if(action == "off") { // a=off digitalWrite(2, HIGH); // 熄滅板載led server.send ( 200, "text/html", "Pin 2 has turn off"); return; } server.send ( 200, "text/html", "unknown action"); return; } server.send ( 200, "text/html", "action no found"); } //3-5-3 網頁修改普通家庭WIFI鏈接帳號密碼 /* WIFI更改處理 * 訪問地址爲htp://192.162.xxx.xxx/wifi?config=on&name=Testwifi&pwd=123456 根據wifi進入 WIFI數據處理函數 根據config的值來進行 on 根據name的值來進行 wifi名字傳輸 根據pwd的值來進行 wifi密碼傳輸 */ void handleWifi(){ if(server.hasArg("config")) { // 請求中是否包含有a的參數 String config = server.arg("config"); // 得到a參數的值 String wifiname; String wifipwd; if(config == "on") { // a=on if(server.hasArg("name")) { // 請求中是否包含有a的參數 wifiname = server.arg("name"); // 得到a參數的值 } if(server.hasArg("pwd")) { // 請求中是否包含有a的參數 wifipwd = server.arg("pwd"); // 得到a參數的值 } String backtxt= "Wifiname: "+ wifiname +"/r/n wifipwd: "+ wifipwd ;// 用於串口和網頁返回信息 Use_Serial.println ( backtxt); // 串口打印給電腦 server.send ( 200, "text/html", backtxt); // 網頁返回給手機提示 // wifi鏈接開始 wifiname.toCharArray(config_wifi.stassid, 50); // 從網頁獲得的 WIFI名 wifipwd.toCharArray(config_wifi.stapsw, 50); //從網頁獲得的 WIFI密碼 saveConfig(); wifi_Init(); return; } else if(config == "off") { // a=off server.send ( 200, "text/html", "config is off!"); return; } server.send ( 200, "text/html", "unknown action"); return; } server.send ( 200, "text/html", "action no found"); } //3-5-4 網頁認證西電上網-- 無用 void http_wifi_xidian(){ //// 經過上網認證,請本身修改postDate中的學號和密碼 // 例如: /*網頁認證上網post*/ // String Referer="http://10.255.44.33/srun_portal_pc.php?ac_id=1&"; // char* host = "10.255.44.33"; // int httpPort = 80; // String host_ur = "srun_portal_pc.php"; /*網頁認證上網模式 */ // String usr_name;//帳號 // String usr_pwd;//密碼 // String postDate = String("")+"action=login&ac_id=1&user_ip=&nas_ip=&user_mac=&url=&username=+"+usr_name+"&password="+usr_pwd; // 認證上網 http_request ruqest; ruqest.Referer="http://10.255.44.33/srun_portal_pc.php?ac_id=1&"; String("10.255.44.33").toCharArray( ruqest.host , 20); ruqest.httpPort = 80; ruqest.host_ur = "srun_portal_pc.php"; ruqest.usr_name="1601120383";//帳號 密碼已修改 要+1 ruqest.usr_pwd="mimaHENFuza";//密碼 密碼已修改 要-1 ruqest.postDate = String("")+"action=login&ac_id=1&user_ip=&nas_ip=&user_mac=&url=&username=+"+ ruqest.usr_name+"&password="+ruqest.usr_pwd; if (hdulogin(ruqest) == 0) { Use_Serial.println("WEB Login Success!"); } else { Use_Serial.println("WEB Login Fail!"); } } //3-5-5-1 網頁認證上網 void handleWifi_wangye(){ if(server.hasArg("config")) { // 請求中是否包含有a的參數 // 1 解析數據是否正常 String config = server.arg("config"); // 得到a參數的值 String wifi_wname,wifi_wpwd,wifi_wip,wifi_postdata; if(config == "on") { // a=on if(server.hasArg("wifi_wname")) { // 請求中是否包含有a的參數 wifi_wname = server.arg("wifi_wname"); // 得到a參數的值 if(wifi_wname.length()==0){ server.send ( 200, "text/html", "please input WIFI名稱!"); // 網頁返回給手機提示 return;} } if(server.hasArg("wifi_wpwd")) { // 請求中是否包含有a的參數 wifi_wpwd = server.arg("wifi_wpwd"); // 得到a參數的值 } if(server.hasArg("wifi_wip")) { // 請求中是否包含有a的參數 wifi_wip = server.arg("wifi_wip"); // 得到a參數的值 if(wifi_wip.length()==0){ server.send ( 200, "text/html", "please input 登錄網址!"); // 網頁返回給手機提示 return;} } if(server.hasArg("wifi_postdata")) { // 請求中是否包含有a的參數 String message=server.arg(3); for (uint8_t i=4; i<server.args(); i++){ message += "&" +server.argName(i) + "=" + server.arg(i) ; } wifi_postdata = message; // 得到a參數的值 if(wifi_postdata.length()==0){ server.send ( 200, "text/html", "please input 聯網信息!"); // 網頁返回給手機提示 return;} } //--------------------------------- wifi鏈接------------------------------------------------- wifi_wname.toCharArray(config_wifi.stassid, 50); // 從網頁獲得的 WIFI名 wifi_wpwd.toCharArray(config_wifi.stapsw, 50); //從網頁獲得的 WIFI密碼 saveConfig(); // wifi鏈接開始 wifi_Init(); //--------------------------------- 認證上網------------------------------------------------- // 2 發送認證 // ruqest.Referer="http://10.255.44.33/srun_portal_pc.php"; http_request ruqest_http; ruqest_http.httpPort = 80; ruqest_http.Referer=wifi_wip;// 登陸網址 ruqest_http.postDate=wifi_postdata; Use_Serial.println (wifi_wip); Use_Serial.println (wifi_postdata); http_jiexi(ruqest_http); return; } else if(config == "off") { // a=off server.send ( 200, "text/html", "config is off!"); return; } server.send ( 200, "text/html", "unknown action"); return; } server.send ( 200, "text/html", "action no found"); } //3-5-5-2 網頁解析IP消息 void http_jiexi(http_request ruqest){ int datStart ; int datEnd; // 1 解析ip // http://10.255.44.33/ char h[]="http://"; char l[]="/"; datStart = ruqest.Referer.indexOf(h)+ strlen(h); datEnd= ruqest.Referer.indexOf(l,datStart); String host=ruqest.Referer.substring(datStart, datEnd); host.toCharArray( ruqest.host , 20); Use_Serial.println ( ruqest.host); // 串口打印給電腦 // 2 解析請求的網頁文件-登陸頁面 // srun_portal_pc.php?ac_id&"; char s[] ="?"; datStart = ruqest.Referer.indexOf(l,datStart)+strlen(l); // datEnd = ruqest.Referer.indexOf(s,datStart)-strlen(s)+1; if(ruqest.Referer.indexOf(s,datStart)==-1) {datEnd = ruqest.Referer.length();} else{ datEnd = ruqest.Referer.indexOf(s,datStart)-1; } ruqest.host_ur = String(ruqest.Referer.substring(datStart, datEnd)); Use_Serial.println ( ruqest.host_ur); // 串口打印給電腦 Use_Serial.println( ruqest.postDate); if (hdulogin(ruqest) == 0) { Use_Serial.println("WEB Login Success!"); } else { Use_Serial.println("WEB Login Fail!"); } return; } //3-5-5-3 網頁認證發送HTTP請求 /*---------------------------------------------------------------*/ int hdulogin(struct http_request ruqest) { WiFiClient client; if (!client.connect(ruqest.host, ruqest.httpPort)) { Use_Serial.println("connection failed"); return 1; } delay(10); if (ruqest.postDate.length() && ruqest.postDate != "0") { String data = (String)ruqest.postDate; int length = data.length(); String postRequest = (String)("POST ") + "/"+ruqest.host_ur+" HTTP/1.1\r\n" + "Host: " +ruqest.host + "\r\n" + "Connection: Keep Alive\r\n" + "Content-Length: " + length + "\r\n" + "Accept:text/html,application/xhtml+xml,application/xml;*/*\r\n" + "Origin: http://"+ruqest.host+"\r\n" + "Upgrade-Insecure-Requests: 1"+"\r\n" + "Content-Type: application/x-www-form-urlencoded;" + "\r\n" + "User-Agent: zyzandESP8266\r\n" + "Accept-Encoding: gzip, deflate"+"\r\n" + "Accept-Language: zh-CN,zh;q=0.9"+"\r\n" + "\r\n" + data + "\r\n"; // String postDate = String("")+"action=login&ac_id=1&user_ip=&nas_ip=&user_mac=&url=&username=+"+usr_name+"&password="+usr_pwd; client.print(postRequest); delay(600); //處理返回信息 String line = client.readStringUntil('\n'); Use_Serial.println(line); while (client.available() > 0) { Use_Serial.println(client.readStringUntil('\n')); line += client.readStringUntil('\n'); // line += client.readStringUntil('\n'); } http_html=line; client.stop(); if (line.indexOf("時間") != -1 || line.indexOf("登錄") != -1) { //認證成功 return 0; } else { return 2; } } client.stop(); return 2; } //3-5-6 網頁測試 void handleTest(){ server.send(200, "text/html", http_html); } //3-5-。。。 網頁沒有對應請求如何處理 void handleNotFound() { String path = server.uri(); Serial.print("load url:"); Serial.println(path); String contentType = getContentType(path); String pathWithGz = path + ".gz"; if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){ if(SPIFFS.exists(pathWithGz)) path += ".gz"; File file = SPIFFS.open(path, "r"); size_t sent = server.streamFile(file, contentType); file.close(); String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET)?"GET":"POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i=0; i<server.args(); i++){ message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } server.send(404, "text/plain", message); return; } String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += ( server.method() == HTTP_GET ) ? "GET" : "POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for ( uint8_t i = 0; i < server.args(); i++ ) { message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n"; } server.send ( 404, "text/plain", message ); } // 解析請求的文件 /** * 根據文件後綴獲取html協議的返回內容類型 */ String getContentType(String filename){ if(server.hasArg("download")) return "application/octet-stream"; else if(filename.endsWith(".htm")) return "text/html"; else if(filename.endsWith(".html")) return "text/html"; else if(filename.endsWith(".css")) return "text/css"; else if(filename.endsWith(".js")) return "application/javascript"; else if(filename.endsWith(".png")) return "image/png"; else if(filename.endsWith(".gif")) return "image/gif"; else if(filename.endsWith(".jpg")) return "image/jpeg"; else if(filename.endsWith(".ico")) return "image/x-icon"; else if(filename.endsWith(".xml")) return "text/xml"; else if(filename.endsWith(".pdf")) return "application/x-pdf"; else if(filename.endsWith(".zip")) return "application/x-zip"; else if(filename.endsWith(".gz")) return "application/x-gzip"; return "text/plain"; } //3-6-1 MQTT初始化 ----------------------------------- void Mqtt_int(){ //MQTT綁定初始化 onoffbutton.setCallback(onoffcallback); mqtt.subscribe(&onoffbutton); } //------mqtt回調函數----------------- void onoffcallback(char *data, uint16_t len) { Serial.print("Hey we're in a onoff callback, the button value is: "); Serial.println(data); } //3-6-2------mqtt鏈接檢測----------------- void MQTT_reconnect() { int8_t ret; // Stop if already connected. if (mqtt.connected()) { return; } Use_Serial.print("Connecting to MQTT... "); uint8_t retries = 3; while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected server.handleClient(); Use_Serial.println(mqtt.connectErrorString(ret)); Use_Serial.println("Retrying MQTT connection in 10 seconds..."); mqtt.disconnect(); delay(10000); // wait 10 seconds retries--; if (retries == 0) { // basically die and wait for WDT to reset me //while (1); Use_Serial.println("Retrying MQTT connection 3 fali..."); return; } } Use_Serial.println("MQTT Connected!"); } ////3-6-3 MQTT主函數 void Mqtt_Domain(){ if(WiFi.status() == WL_CONNECTED){ MQTT_reconnect(); mqtt.processPackets(2000); if(! mqtt.ping()) { mqtt.disconnect(); } } else { wifi_Init(); } } //------------------------------------------- void setup() ------------------------------------------ void setup() { Use_Serial.begin(115200); get_espid(); LED_Int(); loadConfig();// 讀取信息 WIFI wifi_Init(); // 3次嘗試 SET_AP(); // 創建WIFI SPIFFS.begin(); Server_int(); Mqtt_int(); } //------------------------------------------- void void loop() ------------------------------------------ void loop() { server.handleClient(); Mqtt_Domain(); }