ESP8266从点灯到APP控制小车(二)——搭建http网络服务器,实现网页点灯


文章目录

  • ESP8266从点灯到APP控制小车(二)——搭建http网络服务器,实现网页点灯
  • 所需组件
  • 一、三分钟”强行解释“路径访问与http请求
  • 1.路径访问
  • 2.http请求
  • 二、网页点灯
  • 1.开门见山——先点再说(上源码)
  • 2.源码解析
  • 三、练一练
  • 1.课后小作业
  • 2.思路分析
  • 3.参考答案


所需组件

一、三分钟”强行解释“路径访问与http请求

1.路径访问

什么是路径?

例如:D:\Arduino-data\test1

如何进行路径访问?

esp8266wifi小车app制作 esp8266智能小车_web

以上就是为了找到test1.ino,而从D盘路径一层层访问下来

2.http请求

什么是http请求?(https就是加密的http)

在浏览器地址栏上输入https://music.163.com/就会跳转到网易云首页

esp8266wifi小车app制作 esp8266智能小车_服务器_02

可以在后面在加上路径,当访问的路径在服务器有资源时,浏览器就到那个地方,然后加载

esp8266wifi小车app制作 esp8266智能小车_http_03

点击歌单也是同理

esp8266wifi小车app制作 esp8266智能小车_网络_04

其次,当点击具体的歌单时

esp8266wifi小车app制作 esp8266智能小车_网络_05

再携带相应参数进行访问到有对应资源的地方,加载出相应资源(?后面就是参数)

esp8266wifi小车app制作 esp8266智能小车_网络_06

例如:今天去麦当劳,看了下菜单,买了份巨无霸套餐

esp8266wifi小车app制作 esp8266智能小车_esp8266wifi小车app制作_07

  • 域名:www.mcdonalds.com
  • 路径:menu(多个路径:域名/路径1/路径2/路径3?)
  • 参数:bigmac=1(多个参数:?参数1=1&&参数2=A&&参数3=C)

一句话”强行总结“:

通过浏览器地址,输入网址进行请求某个服务器(域名)下某个路径的具体资源(参数索引),服务器下有相应的资源,浏览器便访问到那个地方,然后浏览器加载


一个例子”强行解释“:

浏览器先访问到那个有所需资源地方,相当于我们电脑上先找到那个存放资源的文件夹:

esp8266wifi小车app制作 esp8266智能小车_网络_08

然后浏览器加载资源 =>点击test1.ino打开

esp8266wifi小车app制作 esp8266智能小车_服务器_09


http请求的方式

get请求:

http默认的就是get请求,即直接通过改动网址的某些部分进行访问,会直接到那个访问的地方,如:

post请求:

一句话”强行概况“:

在不改变网址的情况下,通过后台提交请求的方式,访问到具体存放资源的地方,主要用来作数据创建,提交,获取和更新(其实可以类似于在后台去到想访问的地方,提交或者获取东西(完成相应动作)后,又返回根目录;又或者类似与派人从后台去拿资源回来加载)

二、网页点灯

1.开门见山——先点再说(上源码)

/**********************************************************************
项目名称/Project      : ESP8266网页点灯
程序名称/Program name : ESP8266webserver
程序目的/Purpose      : 搭建一个简单的网页,控制ESP8266点亮熄灭LED
项目作者/Author       : ArsenLupin
***********************************************************************/
#include <ESP8266WiFi.h>        // 本程序使用 ESP8266WiFi库
#include <ESP8266WebServer.h>   //  ESP8266WebServer库

// WiFi
const char *ssid = "A"; // 连接得wifi名称
const char *password = "123456789";  // WiFi密码

//创建一个变量led来存放需要控制的引脚号
int led = 2;        

//创建WiFi对象
WiFiClient espClient; 
//创建网络服务器对象,该对象用于响应HTTP请求,监听端口(80)    
ESP8266WebServer webserver(80);  

//处理相应请求的回调函数
void handleRoot();
void handleLEDPost();
void handleLEDGet();
void handleNotFound();

void setup(void){
  Serial.begin(115200);   // 设置窗口波特率,启动串口通讯
  pinMode(led, OUTPUT);   //引脚2为输出模式

  WiFi.begin(ssid, password);       //连接WiFi
  Serial.println("Connecting ...");
                                 
  // WiFi.status()表示的是当前WiFi连接状况,while会让WiFi一直连接成功才跳出
  while (WiFi.status() != WL_CONNECTED) {    
    delay(500);
    Serial.print(".");   
  }                                          

   //当WiFi连接成功,打印连上的WiFi名称和esp8266的ip地址
    Serial.print("\nConnected to ");
    Serial.println(WiFi.SSID());              
    Serial.print("ESP8266-ip:");
    Serial.println(WiFi.localIP());                   

    //创建web服务
    webserver.on("/",handleRoot);  //监听根目录,调用回调函数

    //监听ip地址下的/hello目录,匿名函数回调请求内容,状态码200表示请求成功,返回text类型下的plain类型内容
	webserver.on("/hello",[](){webserver.send(200,"text/plain","hello");});
   
    //监听/LED,监听post请求
    webserver.on("/LED",HTTP_POST,handleLEDPost);
    //监听/led,监听get请求
    webserver.on("/led",HTTP_GET,handleLEDGet);

    //当找不到目录时,匿名函数返回提示
    webserver.onNotFound(handleNotFound);

    //启动web服务
    webserver.begin();
    //告知用户网络服务功能已经启动
    Serial.println("HTTP esp8266-Webserver started");   
}
 
void loop(void){
  //检查http访问,处理客户端连接
  webserver.handleClient();                     
}

//处理根目录访问的回调函数
void handleRoot() {  
    String HTML="<!DOCYPYE html>\
      <html>\
	<head><meta charset='utf-8'></head>\
	<body>你好!ESP8266的web服务器欢迎您!\
  <form action=\"/led\"><input type=\"submit\" value=\"Get led\"></form>\
<form action=\"/LED\" method=\"POST\"><input type=\"submit\" value=\"Post LED\"></form>\
  </body>\
      </html>";     
  webserver.send(200, "text/html", HTML);
}
 
//处理Get访问/LED目录的回调函数
void handleLEDGet() {                          
  digitalWrite(led,!digitalRead(led));// 改变LED的点亮或者熄灭状态
  webserver.send(200,"text/html","Led is Change.");
}

//处理Post访问/LED目录的回调函数
void handleLEDPost() {                          
  digitalWrite(led,!digitalRead(led));      // 改变LED的点亮或者熄灭状态
  webserver.sendHeader("Location","/");     // 跳转回页面根目录
  webserver.send(303);                      // 发送Http相应代码303 跳转  
}

// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){
  webserver.send(404, "text/plain", "404: Not found"); // 发送 HTTP 状态 404 (未找到页面) 并向浏览器发送文字 "404: Not found"
}

2.源码解析

1.引用相应的库,用来连接WiFi和创建web服务

#include <ESP8266WiFi.h>        // 本程序使用 ESP8266WiFi库
#include <ESP8266WebServer.h>   //  ESP8266WebServer库

2.WiFi连接设置

// WiFi连接设置
const char *ssid = "A"; // 连接的wifi名称
const char *password = "123456789";  // WiFi密码

3.创建变量控制引脚

//创建一个变量led来存放需要控制的引脚号
int led = 2;

4.利用库的类来实例化WiFi对象和web对象

//创建WiFi对象
WiFiClient espClient; 
//创建网络服务器对象,该对象用于响应HTTP请求,监听端口(80)    
ESP8266WebServer webserver(80);

5.先声明处理相应请求的回调函数

//处理相应请求的回调函数
void handleRoot();
void handleLEDPost();
void handleLEDGet();
void handleNotFound();

setup()

6.设置串口波特率,设置2号引脚为输出模式

Serial.begin(115200);   // 设置窗口波特率,启动串口通讯
  pinMode(led, OUTPUT);   //引脚2为输出模式

7.调用函数,开始连接WiFi

WiFi.begin(ssid, password);       //连接WiFi
  Serial.println("Connecting ...");

8.利用while循环,当WiFi连接上再跳出循环进行下一步

// WiFi.status()表示的是当前WiFi连接状况,while会让WiFi一直连接成功才跳出
  while (WiFi.status() != WL_CONNECTED) {    
    delay(500);
    Serial.print(".");   
  }

9.当WiFi连接成功,打印连上的WiFi名称和esp8266的ip地址

//当WiFi连接成功,打印连上的WiFi名称和esp8266的ip地址
    Serial.print("\nConnected to ");
    Serial.println(WiFi.SSID());              
    Serial.print("ESP8266-ip:");
    Serial.println(WiFi.localIP());

esp8266wifi小车app制作 esp8266智能小车_esp8266wifi小车app制作_10

浏览器输入ip即可访问(前提是在同一局域网下,且ESP8266连接的WiFi必须是2.4Hz的,一般手机或电脑热点即可)

esp8266wifi小车app制作 esp8266智能小车_网络_11

10.创建并初始化web服务器,监听服务器ip下不同路径的访问,并设置调用相应的函数作出响应(回调)

//创建web服务器,监控不同路径
    webserver.on("/",handleRoot);  //监听根目录,调用回调函数
    //监听ip地址下的/hello目录,匿名函数回调请求内容,状态码200表示请求成功,返回text类型下的plain类型内容
    webserver.on("/hello",[](){webserver.send(200,"text/plain","hello");});
    //监听/led,监听get请求
    webserver.on("/led",HTTP_GET,handleLEDGet);
    //监听/LED,监听post请求
    webserver.on("/LED",HTTP_POST,handleLEDPost);
    //当找不到目录时,匿名函数返回提示
    webserver.onNotFound(handleNotFound);

这里有个地方使用了匿名函数的方式进行监听/hello并回调(看不懂可跳过)

webserver.on(“/hello”,{webserver.send(200,“text/plain”,“hello”);});

esp8266wifi小车app制作 esp8266智能小车_web_12

11.启动web服务,并串口打印告知用户

//启动web服务
    webserver.begin();
    //告知用户网络服务功能已经启动
    Serial.println("HTTP esp8266-Webserver started");

loop()

12.检查http访问,处理客户端连接(目前无需理解)

void loop(void){
  //检查http访问,处理客户端连接
  webserver.handleClient();                     
}

相应回调函数的具体功能

void handleRoot();
void handleLEDPost();
void handleLEDGet();
void handleNotFound();

13.当直接访问ESP8266的ip根目录时(无路径,无参数),调用函数handleRoot

相当于直接访问网易云首页(根目录)

esp8266wifi小车app制作 esp8266智能小车_http_13

webserver.on(“/”,handleRoot); //监听根目录,调用回调函数

//处理根目录访问的回调函数
void handleRoot() {  
    String HTML="<!DOCYPYE html>\
      <html>\
	<head><meta charset='utf-8'></head>\
	<body>你好!ESP8266的web服务器欢迎您!\
  <form action=\"/led\" method=\"GET\"><input type=\"submit\" value=\"Get led\"></form>\
<form action=\"/LED\" method=\"POST\"><input type=\"submit\" value=\"Post LED\"></form>\
  </body>\
      </html>";     
  webserver.send(200, "text/html", HTML);
}

//函数回调相应请求内容,状态码200表示请求成功,返回text类型下的html类型内容

webserver.send(200, “text/html”, HTML);

HMTL里的内容是网页源码(浏览器可以加载然后显示网页),用的是一种标记语言

esp8266wifi小车app制作 esp8266智能小车_esp8266wifi小车app制作_14

红框:ESP8266的ip地址(web服务器地址)

蓝框:浏览器加载出的HTML

14.当访问ESP8266的ip下的/led路径(http://192.168.137.61/led)时,调用函数handleLEDGet

webserver.on(“/led”,HTTP_GET,handleLEDGet); //监听/led,监听get请求

//处理Get访问/LED目录的回调函数
void handleLEDGet() {                          
  digitalWrite(led,!digitalRead(led));// 改变LED的点亮或者熄灭状态
  webserver.send(200,"text/html","Led is Change.");
}

浏览器地址栏输入http://192.168.137.61/led,即会自动调用handleLEDGet

esp8266wifi小车app制作 esp8266智能小车_网络_15

当然,我们也可以通过按钮来实现get请求,还记得HTML吗

之前的HTML是以字符串是形式展现,现在是以它的本来面貌html展现

<!DOCYPYE html>      
<html>	
    <head><meta charset='utf-8'></head>	
    <body>你好!ESP8266的web服务器欢迎您!  
        <form action="/led" method="GET">
            <input type="submit" value="Get led">
        </form>
        <form action="/LED" method="POST">
            <input type="submit" value="Post LED">
        </form>  
    </body>      
</html>

按钮触发get请求

<form action="/led" method="GET">
            <input type="submit" value="Get led">
        </form>

不过,当按下Get led按钮,就直接访问进到了资源界面,我们再想用按钮来控制就不行了,当然,有很多解决的办法,这里不过多介绍,主要介绍能自动返回的Post LED按钮

15.当访问http://192.168.137.61/LED时,调用函数handleLEDPost

webserver.on(“/LED”,HTTP_POST,handleLEDPost); //监听/LED,监听post请求

//处理Post访问/LED目录的回调函数
void handleLEDPost() {                          
  digitalWrite(led,!digitalRead(led));       // 改变LED的点亮或者熄灭状态
  webserver.sendHeader("Location","/");      // 跳转回页面根目录
  webserver.send(303);                       // 发送Http相应代码303 跳转  
}

按钮触发post请求

<form action="/LED" method="POST">
            <input type="submit" value="Post LED">
        </form>

点击后,访问网址没有改变,但led的状态改变了

其实,点击后,它先是访问到/LED,提交了一些东西,然后又返回了,所以它实际上是去到了http://192.168.137.61/LED那个存放资源的地方,进行了函数回调,类似后台访问,没那么直接(个人理解)

esp8266wifi小车app制作 esp8266智能小车_web_16

16.当请求服务器没有的路径时,调用函数handleNotFound

webserver.onNotFound(handleNotFound); //当找不到目录时,匿名函数返回提示

// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){
  webserver.send(404, "text/plain", "404: Not found"); // 发送 HTTP 状态 404 (未找到页面) 并向浏览器发送文字 "404: Not found"
}

三、练一练

1.课后小作业

创建三个网页按钮,来回控制3个引脚输出高低电平信号


2.思路分析

上述源码,我们已经通过一个Post请求的按钮实现了来回控制2号引脚输出电平信号的高低,以此类比进行复制

先多创建两个变量存储需要控制的引脚号

//创建一个变量led来存放需要控制的引脚号
int led = 2;    
int val = 4;
int val2 = 5;

设置引脚为输出模式

pinMode(led, OUTPUT);   //引脚2为输出模式
  pinMode(val, OUTPUT);   //引脚4为输出模式
  pinMode(val2, OUTPUT);   //引脚5为输出模式

确定好对应的访问路径

如:/4,/5

声明相应回调函数

//处理相应请求的回调函数
void handleRoot();
void handleLEDPost();
void handleLEDGet();
void handleNotFound();

void handle4();
void handle5();

设置监听路径,调用相应函数

//监听/4,监听post请求
    webserver.on("/4",HTTP_POST,handle4);
    //监听/5,监听post请求
    webserver.on("/5",HTTP_POST,handle5);

网页上添加相应的触发按钮,修改HTML字符串

<form action="/4" method="POST">
            <input type="submit" value="Post 4">
        </form>  
        <form action="/5" method="POST">
            <input type="submit" value="Post 5">
        </form>

完善相应回调函数的具体功能

webserver.on(“/4”,HTTP_POST,handle4);

//处理Post访问/4目录的回调函数
void handle4() {                          
  digitalWrite(val,!digitalRead(val));       // 改变4的状态
  webserver.sendHeader("Location","/");      // 跳转回页面根目录
  webserver.send(303);                       // 发送Http相应代码303 跳转  
}

webserver.on(“/5”,HTTP_POST,handle5);

//处理Post访问/5目录的回调函数
void handle5() {                          
  digitalWrite(val2,!digitalRead(val2));       // 改变5的状态
  webserver.sendHeader("Location","/");      // 跳转回页面根目录
  webserver.send(303);                       // 发送Http相应代码303 跳转  
}

3.参考答案

/**********************************************************************
项目名称/Project      : ESP8266网页点灯
程序名称/Program name : ESP8266webserverPractice
程序目的/Purpose      : 搭建一个简单的网页,来回控制ESP82663个引脚
项目作者/Author       : ArsenLupin
***********************************************************************/
#include <ESP8266WiFi.h>        // 本程序使用 ESP8266WiFi库
#include <ESP8266WebServer.h>   //  ESP8266WebServer库

// WiFi
const char *ssid = "A"; // 连接的wifi名称
const char *password = "123456789";  // WiFi密码

//创建一个变量led来存放需要控制的引脚号
int led = 2;        
int val = 4;
int val2 = 5;
//创建WiFi对象
WiFiClient espClient; 
//创建网络服务器对象,该对象用于响应HTTP请求,监听端口(80)    
ESP8266WebServer webserver(80);  

//处理相应请求的回调函数
void handleRoot();
void handleLEDPost();
void handleLEDGet();
void handleNotFound();
void handle4();
void handle5();

void setup(void){
  Serial.begin(115200);   // 设置窗口波特率,启动串口通讯
  pinMode(led, OUTPUT);   //引脚2为输出模式
  pinMode(val, OUTPUT);   //引脚4为输出模式
  pinMode(val2, OUTPUT);   //引脚5为输出模式

  WiFi.begin(ssid, password);       //连接WiFi
  Serial.println("Connecting ...");
                                 
  // WiFi.status()表示的是当前WiFi连接状况,while会让WiFi一直连接成功才跳出
  while (WiFi.status() != WL_CONNECTED) {    
    delay(500);
    Serial.print(".");   
  }                                          

   //当WiFi连接成功,打印连上的WiFi名称和esp8266的ip地址
    Serial.print("\nConnected to ");
    Serial.println(WiFi.SSID());              
    Serial.print("ESP8266-ip:");
    Serial.println(WiFi.localIP());                   

    //创建web服务
    webserver.on("/",handleRoot);  //监听根目录,调用回调函数

    //监听ip地址下的/hello目录,匿名函数回调请求内容,状态码200表示请求成功,返回text类型下的plain类型内容
	webserver.on("/hello",[](){webserver.send(200,"text/plain","hello");});
   
    //监听/LED,监听post请求
    webserver.on("/LED",HTTP_POST,handleLEDPost);
    //监听/led,监听get请求
    webserver.on("/led",HTTP_GET,handleLEDGet);

    //监听/4,监听post请求
    webserver.on("/4",HTTP_POST,handle4);
    //监听/5,监听post请求
    webserver.on("/5",HTTP_POST,handle5);

    //当找不到目录时,匿名函数返回提示
    webserver.onNotFound(handleNotFound);

    //启动web服务
    webserver.begin();
    //告知用户网络服务功能已经启动
    Serial.println("HTTP esp8266-Webserver started");   
}
 
void loop(void){
  //检查http访问,处理客户端连接
  webserver.handleClient();                     
}

//处理根目录访问的回调函数
void handleRoot() {  
    String HTML="<!DOCYPYE html>\
      <html>\
	<head><meta charset='utf-8'></head>\
	<body>你好!ESP8266的web服务器欢迎您!\
  <form action=\"/led\" method=\"GET\"><input type=\"submit\" value=\"Get led\"></form>\
<form action=\"/LED\" method=\"POST\"><input type=\"submit\" value=\"Post LED\"></form>\
<form action=\"/4\" method=\"POST\"><input type=\"submit\" value=\"Post 4\"></form>\
<form action=\"/5\" method=\"POST\"><input type=\"submit\" value=\"Post 5\"></form>\
  </body>\
      </html>";     
  webserver.send(200, "text/html", HTML);
}
 
//处理Get访问/LED目录的回调函数
void handleLEDGet() {                          
  digitalWrite(led,!digitalRead(led));// 改变LED的点亮或者熄灭状态
  webserver.send(200,"text/html","Led is Change.");
}

//处理Post访问/LED目录的回调函数
void handleLEDPost() {                          
  digitalWrite(led,!digitalRead(led));      // 改变LED的点亮或者熄灭状态
  webserver.sendHeader("Location","/");     // 跳转回页面根目录
  webserver.send(303);                      // 发送Http相应代码303 跳转  
}

//处理Post访问/4目录的回调函数
void handle4() {                          
  digitalWrite(val,!digitalRead(val));       // 改变4的状态
  webserver.sendHeader("Location","/");      // 跳转回页面根目录
  webserver.send(303);                       // 发送Http相应代码303 跳转  
}

//处理Post访问/5目录的回调函数
void handle5() {                          
  digitalWrite(val2,!digitalRead(val2));       // 改变5的状态
  webserver.sendHeader("Location","/");      // 跳转回页面根目录
  webserver.send(303);                       // 发送Http相应代码303 跳转  
}

// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){
  webserver.send(404, "text/plain", "404: Not found"); // 发送 HTTP 状态 404 (未找到页面) 并向浏览器发送文字 "404: Not found"
}

esp8266wifi小车app制作 esp8266智能小车_网络_17