ESP8266 Máy chủ web nhiều trang
Hướng dẫn này chỉ cho bạn cách biến ESP8266 thành một máy chủ web có thể xử lý nhiều trang đồng thời, chẳng hạn như index.html, temperature.html, led.html, error_404.html, và error_405.html...
Bằng cách làm theo hướng dẫn này, bạn sẽ có thể biến ESP8266 của mình thành một máy chủ web với một số tính năng thú vị:
Nhiều trang web đang hoạt động đồng thời.
Nội dung HTML (bao gồm HTML, CSS và Javascript) cho mỗi trang được lưu riêng trong một tệp trên Arduino IDE.
Nội dung HTML có thể được cập nhật động với các giá trị thời gian thực từ các cảm biến, làm cho các trang web động và đáp ứng.
Máy chủ web cho phép điều khiển một thiết bị được kết nối với ESP8266 thông qua web.
Máy chủ web xử lý các mã lỗi HTTP như 404 Không tìm thấy và 405 Phương thức không được phép
Có thể nghe có vẻ phức tạp, nhưng đừng lo nhé! Hướng dẫn này cung cấp chỉ dẫn từng bước, và mã nguồn được thiết kế thân thiện với người mới bắt đầu, đảm bảo bạn có thể dễ dàng hiểu và tự tạo máy chủ web ESP8266 của riêng mình.
| 1 | × | ESP8266 NodeMCU ESP-12E | | |
| 1 | × | Recommended: ESP8266 NodeMCU ESP-12E (Uno-form) | | |
| 1 | × | USB Cable Type-A to Type-C (for USB-A PC) | | |
| 1 | × | USB Cable Type-C to Type-C (for USB-C PC) | | |
| 1 | × | (Khuyến nghị) Screw Terminal Expansion Board for ESP8266 | | |
| 1 | × | (Khuyến nghị) Power Splitter for ESP8266 Type-C | | |
Or you can buy the following kits:
| 1 | × | DIYables Sensor Kit (30 sensors/displays) | | |
| 1 | × | DIYables Sensor Kit (18 sensors/displays) | | |
Nếu bạn chưa quen với ESP8266 và Web Server (bao gồm sơ đồ chân, cách hoạt động và lập trình), bạn có thể tìm hiểu về chúng qua các bài hướng dẫn sau:
Dưới đây là toàn bộ mã ESP8266 tạo máy chủ web với nhiều trang. Để đơn giản hóa, nội dung HTML cho mỗi trang rất đơn giản và được nhúng trực tiếp vào mã ESP8266. Ở phần sau, chúng ta sẽ học cách tách nội dung HTML cho từng trang thành các tệp riêng biệt, làm cho mã nguồn được tổ chức và dễ quản lý hơn.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#define LED_PIN D5
const char *ssid = "YOUR_WIFI_SSID";
const char *password = "YOUR_WIFI_PASSWORD";
ESP8266WebServer server(80);
int LED_state = LOW;
float getTemperature() {
float temp_x100 = random(0, 10000);
return temp_x100 / 100;
}
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
Serial.print("ESP8266 Web Server's IP address: ");
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, []() {
Serial.println("Web Server: home page");
server.send(200, "text/html", "This is the ESP8266 home page");
});
server.on("/temperature.html", HTTP_GET, []() {
Serial.println("Web Server: temperature page");
float temperature = getTemperature();
server.send(200, "text/html", "Temperature: " + String(temperature));
});
server.on("/led.html", HTTP_GET, []() {
Serial.print("Web Server: LED page");
if (server.arg("state")) {
String state = server.arg("state");
if (state == "on") {
LED_state = HIGH;
} else if (state == "off") {
LED_state = LOW;
}
digitalWrite(LED_PIN, LED_state);
Serial.print(" => turning LED to ");
Serial.print(state);
}
Serial.println();
server.send(200, "text/html", "LED state: " + String(LED_state));
});
server.onNotFound([]() {
if (server.method() == HTTP_GET) {
Serial.println("Web Server: Not Found");
server.send(404, "text/html", "Not Found");
} else {
Serial.println("Web Server: Method Not Allowed");
server.send(405, "text/html", "Method Not Allowed");
}
});
server.begin();
Serial.println("ESP8266 Web server started");
}
void loop() {
server.handleClient();
}
Để bắt đầu với ESP8266 trên Arduino IDE, hãy làm theo các bước sau:
Kết nối các thành phần như được hiển thị trong sơ đồ.
Kết nối bo mạch ESP8266 với máy tính của bạn bằng cáp USB.
Mở Arduino IDE trên máy tính của bạn.
Chọn bo mạch ESP8266 phù hợp, ví dụ NodeMCU 1.0 (ESP-12E Module), và cổng COM tương ứng.
Sao chép mã ở trên và mở bằng Arduino IDE
Thay đổi thông tin Wi-Fi (SSID và mật khẩu) trong mã cho đúng của bạn.
Nhấp nút Tải lên trên Arduino IDE để tải mã lên ESP8266
Mở Serial Monitor
Xem kết quả trên Serial Monitor.
Connecting to WiFi...
Connected to WiFi
ESP8266 Web Server's IP address: 192.168.0.5
ESP8266 Web server started
Bạn sẽ thấy một địa chỉ IP trên Serial Monitor, ví dụ: 192.168.0.5
Nhập lần lượt danh sách sau vào thanh địa chỉ của trình duyệt web trên điện thoại thông minh hoặc máy tính của bạn.
192.168.0.5
192.168.0.5/index.html
192.168.0.5/led.html
192.168.0.5/temperature.html
192.168.0.5/blabla.html
Lưu ý rằng bạn cần thay đổi địa chỉ 192.168.0.5 thành địa chỉ IP bạn nhận được trên Serial Monitor.
Bạn sẽ thấy các trang sau: trang chủ, trang đèn LED, trang nhiệt độ, và trang Không tìm thấy.
Bạn cũng có thể kiểm tra đầu ra trên Serial Monitor.
Connecting to WiFi...
Connected to WiFi
ESP8266 Web Server's IP address: 192.168.0.5
ESP8266 Web server started
Web Server: home page
Web Server: LED page
Web Server: LED page => turning LED to on
Web Server: LED page => turning LED to off
Web Server: temperature page
Web Server: Not Found
Trước đây, mã có nội dung HTML rất đơn giản cho mỗi trang. Tuy nhiên, nếu chúng ta muốn tạo một giao diện bắt mắt với nhiều HTML, mã có thể trở nên lớn và lộn xộn. Để làm cho nó đơn giản hơn, chúng ta sẽ học cách tách HTML khỏi mã ESP8266. Điều này cho phép chúng ta giữ HTML trong các tệp riêng, giúp quản lý và làm việc với nó dễ dàng hơn.
Mở Arduino IDE.
Tạo một bản phác thảo mới và đặt tên cho nó, ví dụ, ESP8266WebServer.ino.
Sao chép mã được cung cấp và dán vào tệp đó.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "index.h"
#include "temperature.h"
#include "led.h"
#include "error_404.h"
#include "error_405.h"
#define LED_PIN D6
const char *ssid = "YOUR_WIFI_SSID";
const char *password = "YOUR_WIFI_PASSWORD";
ESP8266WebServer server(80);
int LED_state = LOW;
float getTemperature() {
float temp_x100 = random(0, 10000);
return temp_x100 / 100;
}
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
Serial.print("ESP8266 Web Server's IP address: ");
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, []() {
Serial.println("Web Server: home page");
String html = HTML_CONTENT_HOME;
server.send(200, "text/html", html);
});
server.on("/temperature.html", HTTP_GET, []() {
Serial.println("Web Server: temperature page");
String html = HTML_CONTENT_TEMPERATURE;
float temperature = getTemperature();
html.replace("%TEMPERATURE_VALUE%", String(temperature));
server.send(200, "text/html", html);
});
server.on("/led.html", HTTP_GET, []() {
Serial.print("Web Server: LED page");
if (server.arg("state")) {
String state = server.arg("state");
if (state == "on") {
LED_state = HIGH;
} else if (state == "off") {
LED_state = LOW;
}
digitalWrite(LED_PIN, LED_state);
Serial.print(" => turning LED to ");
Serial.print(state);
}
Serial.println();
String html = HTML_CONTENT_LED;
html.replace("%LED_STATE%", LED_state ? "ON" : "OFF");
server.send(200, "text/html", html);
});
server.onNotFound([]() {
if (server.method() == HTTP_GET) {
Serial.println("Web Server: Not Found");
String html = HTML_CONTENT_404;
server.send(404, "text/html", html);
} else {
Serial.println("Web Server: Method Not Allowed");
String html = HTML_CONTENT_405;
server.send(405, "text/html", html);
}
});
server.begin();
Serial.println("ESP8266 Web server started");
}
void loop() {
server.handleClient();
}
Thay đổi thông tin WiFi (SSID và mật khẩu) trong mã thành của bạn
Tạo tệp index.h trên Arduino IDE bằng cách:
const char *HTML_CONTENT_HOME = R"=====(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="data:,">
<title>Home Page</title>
</head>
<body>
<h1>Welcome to the Home Page</h1>
<ul>
<li><a href="/led.html">LED Page</a></li>
<li><a href="/temperature.html">Temperature Page</a></li>
</ul>
</body>
</html>
)=====";
const char *HTML_CONTENT_LED = R"=====(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="data:,">
<title>LED Page</title>
</head>
<body>
<h1>LED Page</h1>
<p>LED State: <span style="color: red;">%LED_STATE%</span></p>
<a href='/led.html?state=on'>Turn ON</a>
<br><br>
<a href='/led.html?state=off'>Turn OFF</a>
</body>
</html>
)=====";
const char *HTML_CONTENT_TEMPERATURE = R"=====(
<!DOCTYPE html>
<html>
<head>
<title>ESP8266 - Web Temperature</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7">
<meta charset="utf-8">
<link rel="icon" href="https://diyables.io/images/page/diyables.svg">
<style>
body { font-family: "Georgia"; text-align: center; font-size: width/2pt;}
h1 { font-weight: bold; font-size: width/2pt;}
h2 { font-weight: bold; font-size: width/2pt;}
button { font-weight: bold; font-size: width/2pt;}
</style>
<script>
var cvs_width = 200, cvs_height = 450;
function init() {
var canvas = document.getElementById("cvs");
canvas.width = cvs_width;
canvas.height = cvs_height + 50;
var ctx = canvas.getContext("2d");
ctx.translate(cvs_width/2, cvs_height - 80);
update_view(%TEMPERATURE_VALUE%);
}
function update_view(temp) {
var canvas = document.getElementById("cvs");
var ctx = canvas.getContext("2d");
var radius = 70;
var offset = 5;
var width = 45;
var height = 330;
ctx.clearRect(-cvs_width/2, -350, cvs_width, cvs_height);
ctx.strokeStyle="blue";
ctx.fillStyle="blue";
var x = -width/2;
ctx.lineWidth=2;
for (var i = 0; i <= 100; i+=5) {
var y = -(height - radius)*i/100 - radius - 5;
ctx.beginPath();
ctx.lineTo(x, y);
ctx.lineTo(x - 20, y);
ctx.stroke();
}
ctx.lineWidth=5;
for (var i = 0; i <= 100; i+=20) {
var y = -(height - radius)*i/100 - radius - 5;
ctx.beginPath();
ctx.lineTo(x, y);
ctx.lineTo(x - 25, y);
ctx.stroke();
ctx.font="20px Georgia";
ctx.textBaseline="middle";
ctx.textAlign="right";
ctx.fillText(i.toString(), x - 35, y);
}
ctx.lineWidth=16;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.rect(-width/2, -height, width, height);
ctx.stroke();
ctx.beginPath();
ctx.arc(0, -height, width/2, 0, 2 * Math.PI);
ctx.stroke();
ctx.fillStyle="#e6e6ff";
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.rect(-width/2, -height, width, height);
ctx.fill();
ctx.beginPath();
ctx.arc(0, -height, width/2, 0, 2 * Math.PI);
ctx.fill();
ctx.fillStyle="#ff1a1a";
ctx.beginPath();
ctx.arc(0, 0, radius - offset, 0, 2 * Math.PI);
ctx.fill();
temp = Math.round(temp * 100) / 100;
var y = (height - radius)*temp/100.0 + radius + 5;
ctx.beginPath();
ctx.rect(-width/2 + offset, -y, width - 2*offset, y);
ctx.fill();
ctx.fillStyle="red";
ctx.font="bold 34px Georgia";
ctx.textBaseline="middle";
ctx.textAlign="center";
ctx.fillText(temp.toString() + "°C", 0, 100);
}
window.onload = init;
</script>
</head>
<body>
<h1>ESP8266 - Web Temperature</h1>
<canvas id="cvs"></canvas>
</body>
</html>
)=====";
const char *HTML_CONTENT_404 = R"=====(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="data:,">
<title>404 - Page Not Found</title>
<style>
h1 {color: #ff4040;}
</style>
</head>
<body>
<h1>404</h1>
<p>Oops! The page you are looking for could not be found on Esp32 Web Server.</p>
<p>Please check the URL or go back to the <a href="/">homepage</a>.</p>
<p>Or check <a href="https://esp32io.com/tutorials/esp32-web-server-multiple-pages"> Esp32 Web Server</a> tutorial.</p>
</body>
</html>
)=====";
const char *HTML_CONTENT_405 = R"=====(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="data:,">
<title>405 - Method Not Allowed</title>
<style>
h1 {color: #ff4040;}
</style>
</head>
<body>
<h1>405 - Method Not Allowed</h1>
<p>Oops! The requested method is not allowed for this resource.</p>
<p>Please check your request or go back to the <a href="/">homepage</a>.</p>
<p>Or check <a href="https://esp32io.com/tutorials/esp32-web-server-multiple-pages"> Esp32 Web Server</a> tutorial.</p>
</body>
</html>
)=====";