网络服务器有很多种类型,它们的功能也十分丰富。通常承担网络服务器工作的设备都是运算能力比较强大的电脑。我们的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");
}