ESP8266-Arduino网络编程实例-简单Web服务器(LED控制)

简单Web服务器

在本次实例中,将演示如何实现一个简单的Web服务器控制LED。

1、硬件准备

  • ESP8266 NodeMCU开发板一块
  • LED两个
  • 470欧姆电阻两个
  • 面板板一个
  • 杜邦线若干
  • 数据线一条

在这里插入图片描述

2、软件准备

  • Arduino IDE或VSCode + PlatformIO

在前面的文章中,对如何搭建ESP8266开发环境做了详细的介绍,请参考:

ESP8266 NodeMCU的引脚介绍在前面的文章中做了详细的介绍,请参考:

3、代码实现

Web服务器实现主步骤如下:

第一步:连接网络,请参考:ESP8266-Arduino网络编程实例-接入WiFi网络

第二步:启动WebServer,监听指定端口

第三步:监听客户端连接,发送Web页面文件

第四步:处理客户端请求

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <Arduino.h>
#include <ESP8266WiFi.h>

const char\* ssid = "SSID名称";
const char\* password = "WiFi密码";

// Web服务器对象,监听端口号为80
WiFiServer server(80);

// HTML Header
String header;

// LED状态
String output5State = "off";
String output4State = "off";

// LED引脚
const int output5 = 5;
const int output4 = 4;

// 当前时间
unsigned long currentTime = millis();
// 上次最新时间
unsigned long previousTime = 0;
// 默认超时时长
const long timeoutTime = 2000;

void setup() {
Serial.begin(115200);
// 初始化串口
pinMode(output5, OUTPUT);
pinMode(output4, OUTPUT);
// 关闭LED
digitalWrite(output5, LOW);
digitalWrite(output4, LOW);

// 连接WiFi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// 输出本地IP
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// 启动服务器
server.begin();
}

void sendHeader(WiFiClient\* client){
if(client == NULL){
Serial.println("invalid wifi client");
return;
}

client->println("HTTP/1.1 200 OK");
client->println("Content-type:text/html");
client->println("Connection: close");
client->println();

}

void processingRequest(String header){
if (header.indexOf("GET /5/on") >= 0) {
Serial.println("GPIO 5 on");
output5State = "on";
digitalWrite(output5, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("GPIO 5 off");
output5State = "off";
digitalWrite(output5, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("GPIO 4 on");
output4State = "on";
digitalWrite(output4, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("GPIO 4 off");
output4State = "off";
digitalWrite(output4, LOW);
}
}

// 发送HTML页面
void sendWebPage(WiFiClient\* client){
// HTML head内容
client->println("<!DOCTYPE html><html>");
client->println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client->println("<link rel=\"icon\" href=\"data:,\">");
// 发送CSS样式
client->println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client->println(".button { background-color: #1EDCF5; border: none; color: white; padding: 16px 40px;");
client->println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client->println(".button2 {background-color: #1EF5BC;}</style></head>");

// HTML body内容
client->println("<body><h1>ESP8266 Web Server</h1>");

// 显示LED状态
client->println("<p>GPIO 5 - State " + output5State + "</p>");
if (output5State=="off") {
client->println("<p><a href=\"/5/on\"><button class=\"button\">ON</button></a></p>");
} else {
client->println("<p><a href=\"/5/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client->println("<p>GPIO 4 - State " + output4State + "</p>");
if (output4State=="off") {
client->println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
} else {
client->println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client->println("</body></html>");
client->println();
}

void loop(){
// 客户端连接
WiFiClient client = server.available();
if (client) {
Serial.println("New Client.");
String currentLine = "";
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) {
currentTime = millis();
// 接收数据
if (client.available()) {
char c = client.read();
Serial.write(c);
header += c;
if (c == '\n') {
// 当前请求结束,发送响应
if (currentLine.length() == 0) {
// 发送响应头
sendHeader(&client);
// 处理客户端请求
processingRequest(header);
// 发送HTML页面
sendWebPage(&client);

break;
} else {
// 接收到新行后,当前行更新
currentLine = "";
}
} else if (c != '\r') {
// 当前行未接收完成
currentLine += c;
}
}
}
// 清空
header = "";
// 关闭当前连接
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}

4、代码解析

在示例代码中,首先导入ESP8266 WiFi库

1
2
3
#include <Arduino.h>
#include <ESP8266WiFi.h>

设置连接WiFi的SSID和密码,需要根据实际更改

1
2
3
const char\* ssid     = "SSID";
const char\* password = "SSID密码";

定义Web服务器及监听商品

1
2
WiFiServer server(80);

定义一个字符口串变量用于储存HTML头和内容

1
2
String header;

定义LED状态及引脚

1
2
3
4
5
6
7
8
// LED状态
String output5State = "off";
String output4State = "off";

// LED引脚
const int output5 = 5;
const int output4 = 4;

初始化setup函数

首先,初始化串口

1
2
Serial.begin(115200);

设置LED引脚工作模式及状态设置

1
2
3
4
5
6
7
// 初始化串口
pinMode(output5, OUTPUT);
pinMode(output4, OUTPUT);
// 关闭LED
digitalWrite(output5, LOW);
digitalWrite(output4, LOW);

连接WiFi

1
2
3
4
5
6
7
// 连接WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

连接成功后,输出分配的IP

1
2
3
4
5
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

启动Web服务器

1
2
3
// 启动服务器
server.begin();

loop函数中监听HTTP客户端和处理客户端请求

首先,监听新的客户端连接

1
2
WiFiClient client = server.available();

当收到来自客户端的请求时,我们将保存传入的数据并响应客户端。 只要客户端保持连接,随后的 while 循环就会运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (client) {                           
Serial.println("New Client.");
String currentLine = "";
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) {
currentTime = millis();
// 接收数据
if (client.available()) {
char c = client.read();
Serial.write(c);
header += c;
if (c == '\n') {
// 当前请求结束,发送响应
if (currentLine.length() == 0) {
// 发送响应头
sendHeader(&client);

1
2
3
4
5
6
7
8
9
10
11
12
13
void sendHeader(WiFiClient\* client){
if(client == NULL){
Serial.println("invalid wifi client");
return;
}

client->println("HTTP/1.1 200 OK");
client->println("Content-type:text/html");
client->println("Connection: close");
client->println();

}

当客户端收到连接响应后,接下来就是处理客户端的请求逻辑

1
2
3
 // 处理客户端请求
processingRequest(header);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void processingRequest(String header){
if (header.indexOf("GET /5/on") >= 0) {
Serial.println("GPIO 5 on");
output5State = "on";
digitalWrite(output5, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("GPIO 5 off");
output5State = "off";
digitalWrite(output5, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("GPIO 4 on");
output4State = "on";
digitalWrite(output4, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("GPIO 4 off");
output4State = "off";
digitalWrite(output4, LOW);
}
}

向客户端输出HTML页面

1
2
3
// 发送HTML页面
sendWebPage(&client);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 发送HTML页面
void sendWebPage(WiFiClient\* client){
// HTML head内容
client->println("<!DOCTYPE html><html>");
client->println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client->println("<link rel=\"icon\" href=\"data:,\">");
// 发送CSS样式
client->println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client->println(".button { background-color: #1EDCF5; border: none; color: white; padding: 16px 40px;");
client->println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client->println(".button2 {background-color: #1EF5BC;}</style></head>");

// HTML body内容
client->println("<body><h1>ESP8266 Web Server</h1>");

// 显示LED状态
client->println("<p>GPIO 5 - State " + output5State + "</p>");
if (output5State=="off") {
client->println("<p><a href=\"/5/on\"><button class=\"button\">ON</button></a></p>");
} else {
client->println("<p><a href=\"/5/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client->println("<p>GPIO 4 - State " + output4State + "</p>");
if (output4State=="off") {
client->println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
} else {
client->println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client->println("</body></html>");
client->println();
}

5、运行结果

在这里插入图片描述
在这里插入图片描述

文章来源: https://iotsmart.blog.csdn.net/article/details/127150726