网络服务器有很多种类型,它们的功能也十分丰富。通常承担网络服务器工作的设备都是运算能力比较强大的电脑。我们的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(' '); 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(' '); 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(' '); 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(' '); 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> "; htmlCode+="<head><meta http-equiv='refresh' content='1'/> "; htmlCode+="<title>ESP8266 Button State</title> "; htmlCode+="<style>html {font-family:Helcetica;dispaly:inline-block;margin:0px auto;text-align:center;} "; htmlCode+="body{margin-top:50px} h1{coloe:#444444;margin:50px auto 30px;}h3{color:#444444;margin-bottom:50px;} "; htmlCode+="</style> "; htmlCode+="</head> "; htmlCode+="<body> "; htmlCode+="<h1>ESP8266 BUTTON STATE</h1> "; if(buttonState) { htmlCode+="<p>Button State:HIGH</p> "; } else { htmlCode+="<p>Button State:LOW</p> "; } htmlCode+="</body> "; htmlCode+="</html> "; return htmlCode; } void handleNotFound()//当浏览器访问页面不存在时,通过该函数处理 { /*服务器响应状态码404(未找到浏览器需要的信息),text/plain,表示告诉浏览器接下来要返送信息内容的是一段纯文本信息,信息内容就是404 Not found*/ esp8266_server.send(404,"text/plain","404 Not found"); }