ESP8266-Arduino网络编程实例-Web服务器(从SPIFFS加载页面文件)

Web服务器(从SPIFFS加载页面文件)

本实例将展示如何使用 Arduino IDE 构建一个 Web 服务器,为存储在 ESP8266 NodeMCU 文件系统 (SPIFFS) 上的 HTML 和 CSS 文件提供服务。 我们无需将 HTML 和 CSS 文本写入 Arduino 代码中,而是创建单独的 HTML 和 CSS 文件。

本次Web服务器实现了如下功能:

  • 通过两个按键控制LED的点亮与熄灭
  • 采集BME280环境传感器数据并显示

在前面的文章中,对SPIFFS的使用做了详细的介绍,请参考:

在前面的文章中,使用ESPAsyncWebServer库实现了一个简单的Web服务器,请参考:

在前面的文章中,对BME280的驱动做了详细的介绍,请参考:

1、硬件准备

  • ESP8266 NodeMCU开发板一块
  • 1个LED
  • 1个470欧姆电阻
  • 1个BME280传感器
  • 连接线若干
  • 面包板一个
  • 数据线一条

硬件接线图如下:

在这里插入图片描述

2、软件准备

  • Arduino IDE或VSCode + PlatformIO

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

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

3、代码实现

本次使用到的开源库下载地址如下:

第一步,导入依赖头文件

1
2
3
4
5
6
7
8
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <Wire.h>
#include <Adafruit\_Sensor.h>
#include <Adafruit\_BME280.h>

第二步,定义WiFi连接信息

1
2
3
const char\* ssid = "\*\*\*\*\*";
const char\* ssid_pwd= "\*\*\*\*\*";

第三步,定义设备

1
2
3
4
5
6
Adafruit_BME280 bme; // I2C
// LED
const int ledPin = 2;
// LED状态
String ledState;

第四步,创建Web服务器

1
2
AsyncWebServer server(80);

第五步,BME280数据采集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 读取温度
String getTemperature() {
float temperature = bme.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
//float t = dht.readTemperature(true);
Serial.println(temperature);
return String(temperature);
}
// 读取湿度
String getHumidity() {
float humidity = bme.readHumidity();
Serial.println(humidity);
return String(humidity);
}
// 读取大气压力
String getPressure() {
float pressure = bme.readPressure()/ 100.0F;
Serial.println(pressure);
return String(pressure);
}

第六步,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
String processor(const String& var){
Serial.println(var);
// 处理LED状态
if(var == "STATE"){
if(digitalRead(ledPin)){
ledState = "ON";
}
else{
ledState = "OFF";
}
Serial.print(ledState);
return ledState;
}
else if (var == "TEMPERATURE"){ // 获取温度
return getTemperature();
}
else if (var == "HUMIDITY"){ // 获取湿度
return getHumidity();
}
else if (var == "PRESSURE"){ // 获取气压
return getPressure();
}
return String();
}

第七步,在setup函数中初始化设备

1)初始化串口

1
2
Serial.begin(74880);

2)初始化LED引脚

1
2
pinMode(ledPin, OUTPUT);

3)初始化SPIFFS

1
2
3
4
5
if(!SPIFFS.begin()){ // 初始化SPIFFS
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}

4)初始化BME280

1
2
3
4
5
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}

5)连接WiFi

1
2
3
4
5
6
7
8
9
WiFi.begin(ssid, ssid_pwd);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}

// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());

6)定义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
// 定义根 / 路径
server.on("/", HTTP_GET, [](AsyncWebServerRequest \*request){
request->send(SPIFFS, "/index.html", String(), false, processor); // 从SPIFFS加载index.html文件
});
// 读取css文件
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest \*request){
request->send(SPIFFS, "/style.css", "text/css"); // 从SPIFFS加载css文件
});

// LED点亮
server.on("/on", HTTP_GET, [](AsyncWebServerRequest \*request){
digitalWrite(ledPin, LOW);
request->send(SPIFFS, "/index.html", String(), false, processor);
});
// LED关闭
server.on("/off", HTTP_GET, [](AsyncWebServerRequest \*request){
digitalWrite(ledPin, HIGH);
request->send(SPIFFS, "/index.html", String(), false, processor);
});
// 请求温度
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest \*request){
request->send\_P(200, "text/plain", getTemperature().c\_str());
});
// 请求湿度
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest \*request){
request->send\_P(200, "text/plain", getHumidity().c\_str());
});
// 请求大气压力
server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest \*request){
request->send\_P(200, "text/plain", getPressure().c\_str());
});

整个请求过程如下图所示:

在这里插入图片描述

7)启动web服务器

1
2
server.begin();

第八步,loop不处理任何逻辑

1
2
3
4
void loop(){

}

第九步,编写index.html文件

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
<html>
<head>
<title>ESP8266 Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>ESP8266 Web Server</h1>
<p>GPIO state<strong> %STATE%</strong></p>
<p>
<a href="/on"><button class="button">ON</button></a>
<a href="/off"><button class="button button2">OFF</button></a>
</p>
<p>
<span class="sensor-labels">Temperature</span>
<span id="temperature">%TEMPERATURE%</span>
<sup class="units">&deg;C</sup>
</p>
<p>
<span class="sensor-labels">Humidity</span>
<span id="humidity">%HUMIDITY%</span>
<sup class="units">&#37;</sup>
</p>
<p>
<span class="sensor-labels">Pressure</span>
<span id="pressure">%PRESSURE%</span>
<sup class="units">hPa</sup>
</p>
</body>
<script>
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("temperature").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 10000 ) ;

setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("humidity").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/humidity", true);
xhttp.send();
}, 10000 ) ;

setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("pressure").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/pressure", true);
xhttp.send();
}, 10000 ) ;
</script>
</html>

第十步,编写style.css文件

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
html {
font-family: Arial;
display: inline-block;
margin: 0px auto;
text-align: center;
}
h1 {
color: #0F3376;
padding: 2vh;
}
p {
font-size: 1.5rem;
}
.button {
display: inline-block;
background-color: #008CBA;
border: none;
border-radius: 4px;
color: white;
padding: 16px 40px;
text-decoration: none;
font-size: 30px;
margin: 2px;
cursor: pointer;
}
.button2 {
background-color: #f44336;
}
.units {
font-size: 1.2rem;
}
.sensor-labels {
font-size: 1.5rem;
vertical-align:middle;
padding-bottom: 15px;
}

第十一步,上传Web页面文件到SPIFFS中

在Arduino代码目录下创建data目录,并将index.htmlstyle.css文件复制到该目录下:

在这里插入图片描述

最后将这些文件上传到ESP8266的FLASH中。操作过程请参考:

运行结果:

在这里插入图片描述

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