ESP8266从点灯到APP控制小车(二)——搭建http网络服务器,实现网页点灯
文章目录
- ESP8266从点灯到APP控制小车(二)——搭建http网络服务器,实现网页点灯
- 所需组件
- 一、三分钟”强行解释“路径访问与http请求
- 1.路径访问
- 2.http请求
- 二、网页点灯
- 1.开门见山——先点再说(上源码)
- 2.源码解析
- 三、练一练
- 1.课后小作业
- 2.思路分析
- 3.参考答案
所需组件
- ESP8266开发板
- 已配置好的Arduino IDE环境(配置传送门)
- 数据线
一、三分钟”强行解释“路径访问与http请求
1.路径访问
什么是路径?
例如:D:\Arduino-data\test1
如何进行路径访问?
以上就是为了找到test1.ino,而从D盘路径一层层访问下来
2.http请求
什么是http请求?(https就是加密的http)
在浏览器地址栏上输入https://music.163.com/就会跳转到网易云首页
可以在后面在加上路径,当访问的路径在服务器有资源时,浏览器就到那个地方,然后加载
点击歌单也是同理
其次,当点击具体的歌单时
再携带相应参数进行访问到有对应资源的地方,加载出相应资源(?后面就是参数)
例如:今天去麦当劳,看了下菜单,买了份巨无霸套餐
- 域名:www.mcdonalds.com
- 路径:menu(多个路径:域名/路径1/路径2/路径3?)
- 参数:bigmac=1(多个参数:?参数1=1&&参数2=A&&参数3=C)
一句话”强行总结“:
通过浏览器地址,输入网址进行请求某个服务器(域名)下某个路径的具体资源(参数索引),服务器下有相应的资源,浏览器便访问到那个地方,然后浏览器加载
一个例子”强行解释“:
浏览器先访问到那个有所需资源地方,相当于我们电脑上先找到那个存放资源的文件夹:
然后浏览器加载资源 =>点击test1.ino打开
http请求的方式
get请求:
http默认的就是get请求,即直接通过改动网址的某些部分进行访问,会直接到那个访问的地方,如:
- https://music.163.com/
- https://music.163.com/#/playlist
- https://music.163.com/#/playlist?id=7050074027
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());
浏览器输入ip即可访问(前提是在同一局域网下,且ESP8266连接的WiFi必须是2.4Hz的,一般手机或电脑热点即可)
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”);});
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
相当于直接访问网易云首页(根目录)
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里的内容是网页源码(浏览器可以加载然后显示网页),用的是一种标记语言
红框: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
当然,我们也可以通过按钮来实现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那个存放资源的地方,进行了函数回调,类似后台访问,没那么直接(个人理解)
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"
}