網絡服務器有很多種類型,它們的功能也十分豐富。通常承擔網絡服務器工作的設備都是運算能力比較強大的電腦。我們的ESP866-NodeMCU雖然也能實現網絡服務器的一些功能,但是畢竟它的運算能力是無法與那些昂貴的服務器電腦相媲美的,因此ESP8266-NodeMCU只能實現一些基本的網絡服務功能。不過這些基本的網絡服務功能已經足夠我們開發物聯網項目了。在接下來的幾節教程里,我們將一起來學習如何讓ESP8266-NodeMCU來實現網絡服務功能。
網絡服務是一個很寬泛的概念,我們在這里即將給您介紹的是網絡服務中的網頁服務功能。所謂網頁服務就是專門用於網頁瀏覽的服務。
一、使用瀏覽器訪問ESP8266服務器
代碼:
#include <ESP8266WiFi.h> #include <ESP8266WiFiMulti.h> #include <ESP8266WebServer.h> ESP8266WiFiMulti WiFiMulti;//建立ESP8266WiFiMulti對象,對象名稱為WiFiMulti ESP8266WebServer esp8266_server(80);//建立ESP8266WebServer對象,對象名稱是“esp8266_server” //括號中的數字是網絡服務器響應http請求的端口號 //網絡服務器http端口號為80,因此這里使用80為端口號 int led=14;//設置指示燈 void setup() { pinMode(led,OUTPUT); Serial.begin(9600); WiFiMulti.addAP("vivo","QiFei159874");//這條指令就是告訴ESP8266下面會告訴你多個WiFi網絡名稱和密碼 WiFiMulti.addAP("vivo1","qifei159874");//注意這里的雙引號要加上,沒加報錯 WiFiMulti.addAP("vivo2","QIFEI159874");// digitalWrite(led,HIGH);//默認LED是熄滅的 //運行自定義函數,當未連接到路由器的過程中,閃爍LED,直到連接成功,點亮LED //gotowifi(); Serial.println("WiFi正在連接中"); int i=0; while(WiFiMulti.run()!=WL_CONNECTED)//WiFiMulti.run()和WiFi.Status()功能一樣,都是用來表示當前WiFi連接的狀態 { delay(1000); Serial.print("."); } Serial.println('\n'); Serial.print("連接到"); Serial.println(WiFi.SSID()); Serial.print("IP Address: "); Serial.println(WiFi.localIP());//ESP8266的IP地址 /*-------------”啟動網絡服務功能“程序部分開始------------*/ esp8266_server.begin();//啟動網絡服務器 esp8266_server.on("/",handleRoot);//on函數的作用就是提供頁面服務,告訴MCU通過那個函數訪問這個界面“/”頁面,就是主頁,通過handleRoot函數處理該頁面 esp8266_server.onNotFound(handleNotFound);//當請求頁面不存在時,通過該函數處理 //----啟動網路服務功能部分結束 Serial.println("HTTP esp8266_server Started");//告知用戶ESP8266網絡服務功能已經啟動 } void loop() { esp8266_server.handleClient();//處理HTTP服務器訪問 } void handleRoot() { /*服務器響應狀態碼200(找到信息了),text/plain,表示告訴瀏覽器接下來要返送信息內容的是一段純文本信息,信息內容就是Hello from ESP8266 */ esp8266_server.send(200,"text/plain","Hello from ESP8266");//nodeMCU將調用 } void handleNotFound()//當瀏覽器訪問頁面不存在時,通過該函數處理 { /*服務器響應狀態碼404(未找到瀏覽器需要的信息),text/plain,表示告訴瀏覽器接下來要返送信息內容的是一段純文本信息,信息內容就是404 Not found*/ esp8266_server.send(404,"text/plain","404 Not found"); }
將上述代碼下載到ESP8266后,在復位之后,通過串口查看ESP8266網絡服務器的IP地址如圖1,將其復制到瀏覽器打開可以看到如圖2的現象,這說明已經成功建立了一個網絡服務器。
在IP地址后在加一些頁面再次訪問,因為在代碼中我們沒有寫led的界面,也就是說我們訪問的頁面不存在,所以得到了如圖3的結果,這也就是我們做的另一個頁面了。
圖1
圖2
圖3
二、通過瀏覽器訪問ESP8266服務器進行簡單的操作(點亮和熄滅LED)。
實驗代碼
#include <ESP8266WiFi.h> #include <ESP8266WiFiMulti.h> #include <ESP8266WebServer.h> ESP8266WiFiMulti WiFiMulti;//建立ESP8266WiFiMulti對象,對象名稱為WiFiMulti ESP8266WebServer esp8266_server(80);//建立ESP8266WebServer對象,對象名稱是“esp8266_server” //括號中的數字是網絡服務器響應http請求的端口號 //網絡服務器http端口號為80,因此這里使用80為端口號 int LED=D5;//設置指示燈 void setup() { pinMode(LED,OUTPUT); Serial.begin(9600); WiFiMulti.addAP("vivo","QiFei159874");//這條指令就是告訴ESP8266下面會告訴你多個WiFi網絡名稱和密碼 WiFiMulti.addAP("vivo1","qifei159874");//注意這里的雙引號要加上,沒加報錯 WiFiMulti.addAP("vivo2","QIFEI159874");// digitalWrite(LED,HIGH);//默認LED是熄滅的 //運行自定義函數,當未連接到路由器的過程中,閃爍LED,直到連接成功,點亮LED //gotowifi(); Serial.println("WiFi正在連接中"); int i=0; while(WiFiMulti.run()!=WL_CONNECTED)//WiFiMulti.run()和WiFi.Status()功能一樣,都是用來表示當前WiFi連接的狀態 { delay(1000); Serial.print("."); } Serial.println('\n'); Serial.print("連接到"); Serial.println(WiFi.SSID()); Serial.print("IP Address: "); Serial.println(WiFi.localIP());//ESP8266的IP地址 /*-------------”啟動網絡服務功能“程序部分開始------------*/ esp8266_server.begin();//啟動網絡服務器 esp8266_server.on("/",HTTP_GET,handleRoot);//on函數的作用就是提供頁面服務,告訴MCU通過那個函數訪問這個界面“/”頁面,就是主頁,通過handleRoot函數處理該頁面 esp8266_server.on("/LED",HTTP_POST,handleLED);//設置處理LED控制請求的函數“handleLED” esp8266_server.onNotFound(handleNotFound);//當請求頁面不存在時,通過該函數處理 //----啟動網路服務功能部分結束 Serial.println("HTTP esp8266_server Started");//告知用戶ESP8266網絡服務功能已經啟動 } void loop() { esp8266_server.handleClient();//處理HTTP服務器訪問 } void handleRoot() { /*服務器響應狀態碼200(找到信息了),text/plain,表示告訴瀏覽器接下來要返送信息內容的是一段純文本信息,信息內容就是Hello from ESP8266 */ esp8266_server.send(200, "text/html", "<form action=\"/LED\" method=\"POST\"><input type=\"submit\" value=\"Toggle LED\"></form>");//nodeMCU將調用html內容,這是一個按鈕 //啊啊啊啊啊,這里犯了一個巨蠢的錯誤,由於 input type 拼寫錯誤,沒報錯,可以上傳,就是不顯示界面:<>: // esp8266_server.send(200, "text/html", "<form action=\"/LED\" method=\"POST\"><input type=\"submit\" value=\"Toggle LED\"></form>"); } void handleLED() { digitalWrite(LED,!digitalRead(LED));//改變LED的狀態 esp8266_server.sendHeader("Location","/");//跳轉回頁面根目錄 esp8266_server.send(303);//發送HTTP相應代碼303 跳轉到另一個界面} } void handleNotFound()//當瀏覽器訪問頁面不存在時,通過該函數處理 { /*服務器響應狀態碼404(未找到瀏覽器需要的信息),text/plain,表示告訴瀏覽器接下來要返送信息內容的是一段純文本信息,信息內容就是404 Not found*/ esp8266_server.send(404,"text/plain","404 Not found"); }
通過串口打印的信息如圖4,將IP地址輸入到瀏覽器中,點擊顯示圖標,就可以觀測到現象。
圖4
網頁顯示如圖5
圖5s
三、通過網絡服務將ESP8266的引腳狀態顯示在網頁上(手動刷新)。
如圖6所顯示的是實時刷新的按鍵狀態,按鍵設置為上拉輸入模式,所以當按鍵按下后檢測為低電平。松開后又變成高電平。這個代碼有個缺點就是需要刷新頁面才可以顯示當前的狀態。
圖6
網頁界面如圖7所示
圖7
代碼:
#include <ESP8266WiFi.h> #include <ESP8266WiFiMulti.h> #include <ESP8266WebServer.h> ESP8266WiFiMulti WiFiMulti;//建立ESP8266WiFiMulti對象,對象名稱為WiFiMulti ESP8266WebServer esp8266_server(80);//建立ESP8266WebServer對象,對象名稱是“esp8266_server” //括號中的數字是網絡服務器響應http請求的端口號 //網絡服務器http端口號為80,因此這里使用80為端口號 int LED=D5;//設置指示燈 int BUTTON=D1;//設置按鍵引腳/*D0不知道為啥不可以,在第一次按鍵按下之后就會保持為低電平,只有復位才可以恢復高電平,所以改用使用D1,成功*/ bool pinState;//存儲按鍵的狀態 void setup() { pinMode(LED,OUTPUT); pinMode(BUTTON,INPUT_PULLUP);//將按鍵設置為上拉輸入。 Serial.begin(9600); WiFiMulti.addAP("vivo","QiFei159874");//這條指令就是告訴ESP8266下面會告訴你多個WiFi網絡名稱和密碼 WiFiMulti.addAP("vivo1","qifei159874");//注意這里的雙引號要加上,沒加報錯 WiFiMulti.addAP("vivo2","QIFEI159874");// digitalWrite(LED,HIGH);//默認LED是熄滅的 //運行自定義函數,當未連接到路由器的過程中,閃爍LED,直到連接成功,點亮LED //gotowifi(); Serial.println("WiFi正在連接中"); int i=0; while(WiFiMulti.run()!=WL_CONNECTED)//WiFiMulti.run()和WiFi.Status()功能一樣,都是用來表示當前WiFi連接的狀態 { delay(1000); Serial.print("."); } Serial.println('\n'); Serial.print("連接到"); Serial.println(WiFi.SSID()); Serial.print("IP Address: "); Serial.println(WiFi.localIP());//ESP8266的IP地址 /*-------------”啟動網絡服務功能“程序部分開始------------*/ esp8266_server.begin();//啟動網絡服務器 esp8266_server.on("/",HTTP_GET,handleRoot);//on函數的作用就是提供頁面服務,告訴MCU通過那個函數訪問這個界面“/”頁面,就是主頁,通過handleRoot函數處理該頁面 esp8266_server.onNotFound(handleNotFound);//當請求頁面不存在時,通過該函數處理 //----啟動網路服務功能部分結束 Serial.println("HTTP esp8266_server Started");//告知用戶ESP8266網絡服務功能已經啟動 } void loop() { esp8266_server.handleClient();//處理HTTP服務器訪問 pinState=digitalRead(BUTTON); Serial.println(digitalRead(BUTTON)); } void handleRoot() { String displayPinState;//存儲按鍵狀態的字符串變量 if(pinState==HIGH)//當按鍵為高電平時 { displayPinState="Pin State=HIGH";//字符串賦值高電平信息 } else { displayPinState="Pin State=LOW"; } esp8266_server.send(200,"text/plaint",displayPinState); } void handleNotFound()//當瀏覽器訪問頁面不存在時,通過該函數處理 { /*服務器響應狀態碼404(未找到瀏覽器需要的信息),text/plain,表示告訴瀏覽器接下來要返送信息內容的是一段純文本信息,信息內容就是404 Not found*/ esp8266_server.send(404,"text/plain","404 Not found"); }
四、通過網絡服務將ESP8266的引腳狀態顯示在網頁上。(自動刷新)
代碼
#include <ESP8266WiFi.h> #include <ESP8266WiFiMulti.h> #include <ESP8266WebServer.h> ESP8266WiFiMulti WiFiMulti;//建立ESP8266WiFiMulti對象,對象名稱為WiFiMulti ESP8266WebServer esp8266_server(80);//建立ESP8266WebServer對象,對象名稱是“esp8266_server” //括號中的數字是網絡服務器響應http請求的端口號 //網絡服務器http端口號為80,因此這里使用80為端口號 int LED=D5;//設置指示燈 int BUTTON=D1;//設置按鍵引腳 bool pinState;//存儲按鍵的狀態 void setup() { pinMode(LED,OUTPUT); pinMode(BUTTON,INPUT_PULLUP);//將按鍵設置為上拉輸入。 Serial.begin(9600); WiFiMulti.addAP("vivo","QiFei159874");//這條指令就是告訴ESP8266下面會告訴你多個WiFi網絡名稱和密碼 WiFiMulti.addAP("vivo1","qifei159874");//注意這里的雙引號要加上,沒加報錯 WiFiMulti.addAP("vivo2","QIFEI159874");// digitalWrite(LED,HIGH);//默認LED是熄滅的 //運行自定義函數,當未連接到路由器的過程中,閃爍LED,直到連接成功,點亮LED //gotowifi(); Serial.println("WiFi正在連接中"); int i=0; while(WiFiMulti.run()!=WL_CONNECTED)//WiFiMulti.run()和WiFi.Status()功能一樣,都是用來表示當前WiFi連接的狀態 { delay(1000); Serial.print("."); } Serial.println('\n'); Serial.print("連接到"); Serial.println(WiFi.SSID()); Serial.print("IP Address: "); Serial.println(WiFi.localIP());//ESP8266的IP地址 /*-------------”啟動網絡服務功能“程序部分開始------------*/ esp8266_server.begin();//啟動網絡服務器 esp8266_server.on("/",handleRoot);//on函數的作用就是提供頁面服務,告訴MCU通過那個函數訪問這個界面“/”頁面,就是主頁,通過handleRoot函數處理該頁面 esp8266_server.onNotFound(handleNotFound);//當請求頁面不存在時,通過該函數處理 //----啟動網路服務功能部分結束 Serial.println("HTTP esp8266_server Started");//告知用戶ESP8266網絡服務功能已經啟動 } void loop() { esp8266_server.handleClient();//處理HTTP服務器訪問 pinState=digitalRead(BUTTON); //Serial.println(digitalRead(BUTTON)); } void handleRoot()//處理網站目錄“/”的訪問請求 { esp8266_server.send(200,"text/html",SendHtml(pinState)); } String SendHtml(bool buttonState) { String htmlCode="<!DOCTYPE html><html>\n"; htmlCode+="<head><meta http-equiv='refresh' content='1'/>\n"; htmlCode+="<title>ESP8266 Button State</title>\n"; htmlCode+="<style>html {font-family:Helcetica;dispaly:inline-block;margin:0px auto;text-align:center;}\n"; htmlCode+="body{margin-top:50px} h1{coloe:#444444;margin:50px auto 30px;}h3{color:#444444;margin-bottom:50px;}\n"; htmlCode+="</style>\n"; htmlCode+="</head>\n"; htmlCode+="<body>\n"; htmlCode+="<h1>ESP8266 BUTTON STATE</h1>\n"; if(buttonState) { htmlCode+="<p>Button State:HIGH</p>\n"; } else { htmlCode+="<p>Button State:LOW</p>\n"; } htmlCode+="</body>\n"; htmlCode+="</html>\n"; return htmlCode; } void handleNotFound()//當瀏覽器訪問頁面不存在時,通過該函數處理 { /*服務器響應狀態碼404(未找到瀏覽器需要的信息),text/plain,表示告訴瀏覽器接下來要返送信息內容的是一段純文本信息,信息內容就是404 Not found*/ esp8266_server.send(404,"text/plain","404 Not found"); }