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...

trình duyệt web ESP8266 NodeMCU

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ị:

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.

Phần cứng cần chuẩn bị

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)

Về ESP8266 và Máy chủ Web

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:

ESP8266 Mã nguồn - Máy chủ web đa trang

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.

/* * Mã ESP8266 NodeMCU này được phát triển bởi newbiely.vn * Mã ESP8266 NodeMCU này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/esp8266/esp8266-web-server-multiple-pages */ #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #define LED_PIN D5 // The ESP8266 pin D5 connected to LED const char *ssid = "YOUR_WIFI_SSID"; // CHANGE IT const char *password = "YOUR_WIFI_PASSWORD"; // CHANGE IT ESP8266WebServer server(80); // Web server on port 80 int LED_state = LOW; float getTemperature() { // YOUR SENSOR IMPLEMENTATION HERE // simulate the temperature value float temp_x100 = random(0, 10000); // a ramdom value from 0 to 10000 return temp_x100 / 100; // return the simulated temperature value from 0 to 100 in float } void setup() { Serial.begin(9600); pinMode(LED_PIN, OUTPUT); // Connect to Wi-Fi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); // Print the ESP8266's IP address Serial.print("ESP8266 Web Server's IP address: "); Serial.println(WiFi.localIP()); // Serve the specified HTML pages 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"); // Check for the 'state' parameter in the query string if (server.arg("state")) { String state = server.arg("state"); if (state == "on") { LED_state = HIGH; } else if (state == "off") { LED_state = LOW; } // control LED here 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)); }); // 404 and 405 error handler server.onNotFound([]() { if (server.method() == HTTP_GET) { // Handle 404 Not Found error Serial.println("Web Server: Not Found"); server.send(404, "text/html", "Not Found"); } else { // Handle 405 Method Not Allowed error 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() { // Handle client requests server.handleClient(); // Your code can go here or be empty; the server is handled asynchronously }

Hướng dẫn từng bước

Để bắt đầu với ESP8266 trên Arduino IDE, hãy làm theo các bước sau:

  • Xem bài hướng dẫn ESP8266 - Cài đặt phần mềm nếu đây là lần đầu bạn sử dụng ESP8266.
  • 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.
COM6
Send
Connecting to WiFi... Connected to WiFi ESP8266 Web Server's IP address: 192.168.0.5 ESP8266 Web server started
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  
  • 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.
COM6
Send
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
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  

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ã ESP8266 - Máy chủ web đa trang hoàn chỉnh

  • 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 đó.
/* * Mã ESP8266 NodeMCU này được phát triển bởi newbiely.vn * Mã ESP8266 NodeMCU này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/esp8266/esp8266-web-server-multiple-pages */ #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 // The ESP8266 pin connected to LED const char *ssid = "YOUR_WIFI_SSID"; // CHANGE IT const char *password = "YOUR_WIFI_PASSWORD"; // CHANGE IT ESP8266WebServer server(80); // Web server on port 80 int LED_state = LOW; float getTemperature() { // YOUR SENSOR IMPLEMENTATION HERE // simulate the temperature value float temp_x100 = random(0, 10000); // a ramdom value from 0 to 10000 return temp_x100 / 100; // return the simulated temperature value from 0 to 100 in float } void setup() { Serial.begin(9600); pinMode(LED_PIN, OUTPUT); // Connect to Wi-Fi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); // Print the ESP8266's IP address Serial.print("ESP8266 Web Server's IP address: "); Serial.println(WiFi.localIP()); // Serve the specified HTML pages server.on("/", HTTP_GET, []() { Serial.println("Web Server: home page"); String html = HTML_CONTENT_HOME; // Use the HTML content from the index.h file server.send(200, "text/html", html); }); server.on("/temperature.html", HTTP_GET, []() { Serial.println("Web Server: temperature page"); String html = HTML_CONTENT_TEMPERATURE; // Use the HTML content from the temperature.h file float temperature = getTemperature(); html.replace("%TEMPERATURE_VALUE%", String(temperature)); // update the temperature value server.send(200, "text/html", html); }); server.on("/led.html", HTTP_GET, []() { Serial.print("Web Server: LED page"); // Check for the 'state' parameter in the query string if (server.arg("state")) { String state = server.arg("state"); if (state == "on") { LED_state = HIGH; } else if (state == "off") { LED_state = LOW; } // control LED here digitalWrite(LED_PIN, LED_state); Serial.print(" => turning LED to "); Serial.print(state); } Serial.println(); String html = HTML_CONTENT_LED; // Use the HTML content from the led.h file html.replace("%LED_STATE%", LED_state ? "ON" : "OFF"); // update the LED state server.send(200, "text/html", html); }); // 404 and 405 error handler server.onNotFound([]() { if (server.method() == HTTP_GET) { // Handle 404 Not Found error Serial.println("Web Server: Not Found"); String html = HTML_CONTENT_404; // Use the HTML content from the error_404.h file server.send(404, "text/html", html); } else { // Handle 405 Method Not Allowed error Serial.println("Web Server: Method Not Allowed"); String html = HTML_CONTENT_405; // Use the HTML content from the error_405.h file server.send(405, "text/html", html); } }); server.begin(); Serial.println("ESP8266 Web server started"); } void loop() { // Handle client requests server.handleClient(); // Your code can go here or be empty; the server is handled asynchronously }
  • 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:
    • Hoặc nhấp vào nút ngay dưới biểu tượng Serial Monitor và chọn New Tab, hoặc dùng phím Ctrl+Shift+N
    Arduino ide 2 thêm tệp
    • Đặt tên cho tệp là index.h và nhấn nút OK
    Arduino ide 2 thêm tệp index.h
    • Sao chép mã dưới đây và dán vào tệp index.h.
    /* * Mã ESP8266 NodeMCU này được phát triển bởi newbiely.vn * Mã ESP8266 NodeMCU này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/esp8266/esp8266-web-server-multiple-pages */ 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> )=====";
    • Tương tự, hãy tạo file led.h trên Arduino IDE với nội dung sau.
    /* * Mã ESP8266 NodeMCU này được phát triển bởi newbiely.vn * Mã ESP8266 NodeMCU này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/esp8266/esp8266-web-server-multiple-pages */ 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> )=====";
    • Tương tự, hãy tạo tệp temperature.h trên Arduino IDE với nội dung sau đây.
    /* * Mã ESP8266 NodeMCU này được phát triển bởi newbiely.vn * Mã ESP8266 NodeMCU này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/esp8266/esp8266-web-server-multiple-pages */ 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"; //5-step Degree 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(); } //20-step Degree 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); } // shape 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> )=====";
    • Tương tự, tạo tệp error_404.h trên Arduino IDE với nội dung sau.
    /* * Mã ESP8266 NodeMCU này được phát triển bởi newbiely.vn * Mã ESP8266 NodeMCU này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/esp8266/esp8266-web-server-multiple-pages */ 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> )=====";
    • Tương tự, hãy tạo tệp error_405.h trong Arduino IDE với nội dung sau.
    /* * Mã ESP8266 NodeMCU này được phát triển bởi newbiely.vn * Mã ESP8266 NodeMCU này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/esp8266/esp8266-web-server-multiple-pages */ 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> )=====";
    • Bây giờ bạn có nhiều tệp tin trên Arduino IDE như dưới đây:
    Arduino ide 2 nhiều tệp tin
    • Nhấn nút Tải lên trong Arduino IDE để tải mã nguồn lên ESP8266
    • Truy cập lần lượt các trang web của bo mạch ESP8266 bằng trình duyệt web như trước đây. Bạn sẽ thấy tất cả các trang web như dưới đây:
    ESP8266 NodeMCU nhiều trang web