Bài 12. Webserver trên ESP8266 nodemcu

Webserver trên esp8266 là một ứng dụng cho phép esp8266 hoạt động như một máy chủ web, có thể nhận và phản hồi các yêu cầu từ các thiết bị khác qua wifi. Bạn có thể lập trình cho esp8266 bằng Arduino IDE và sử dụng ngôn ngữ HTML để thiết kế giao diện web. Bạn có thể điều khiển các chân GPIO của esp8266 qua webserver để thực hiện các chức năng khác nhau như bật tắt LED, đọc cảm biến, giao tiếp với các thiết bị khác, v.v. Trong bài viết này Điện thông minh E-smart sẽ hướng dẫn các bạn thiết lập một webserver trên esp8266.

Webserver trên esp8266

Thêm đối tượng webserver

Thư viện ESP8266WebServer là một thư viện có sẵn trong Arduino IDE, giúp bạn tạo một webserver trên esp8266 một cách dễ dàng. Bạn chỉ cần khai báo thư viện này ở đầu code, và tạo một đối tượng webserver với port 80. Port là một số nhận dạng cho một kênh giao tiếp trên mạng. Port 80 là port mặc định cho giao thức HTTP, là giao thức mà webserver và trình duyệt sử dụng để giao tiếp.

//Khai báo thư viện
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

//Khai báo đối tượng webserver, sử dụng port 80
ESP8266WebServer server(80);

Thiết lập giao diện web bằng html

Webserver trên esp8266

Mã nguồn html là một chuỗi các thẻ (tag) và nội dung được trình duyệt hiển thị theo cách định dạng. Để tạo giao diện web cho webserver, bạn cần lưu trữ mã nguồn html trong một biến. Ở đây tôi dùng biến kiểu const char* R”html, kiểu này là một kiểu dữ liệu khác để lưu trữ mã nguồn html trong Arduino IDE. Kiểu này sử dụng cú pháp raw string literal, cho phép bạn viết mã nguồn html một cách trực quan, không cần thêm ký tự \n hay \ để xuống dòng hoặc thoát khỏi các ký tự đặc biệt.

Để khai báo biến chứa mã nguồn html dùng kiểu const char* R”html, bạn cần thêm ký tự R”html( ở đầu và )html” ở cuối của chuỗi html. Ví dụ:

//Khai báo biến chứa mã nguồn html dùng kiểu const char* R"html
const char* html = R"html(
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
      button {
        width:200px;
        height:100px;
        font-size:36px;
      }
    </style>
  </head>
  <body>
    <h1>Webserver trên ESP8266</h1>
    <p>Điều khiển LED qua giao diện web</p>
    <p><a href="/led/on"><button>Bật LED</button></a></p>
    <p><a href="/led/off"><button>Tắt LED</button></a></p>
  </body>
</html>
)html";

Viết hàm khởi tạo và xử lý webserver

Trong phần này, tôi sẽ lấy ví dụ về khởi tạo một webserver có chức năng điều khiển ON/OFF LED trên kít nodemcu esp8266 qua giao diện web. Lúc này chúng ta thực hiện như sau:

Khởi tạo webserver trên esp8266

Chúng ta viết một hàm setupServer() để khởi tạo webserver. Bạn cần gọi hàm này trong hàm setup() của Arduino IDE. Trong hàm setupServer(), bạn sẽ thực hiện các công việc sau:

  • Thiết lập chân LED là output và tắt LED.
  • Kết nối esp8266 với wifi và in ra địa chỉ IP của esp8266 trên cổng nối tiếp.
  • Định nghĩa các hàm xử lý yêu cầu từ người dùng. Có bốn loại yêu cầu mà webserver sẽ xử lý:
    • Yêu cầu gốc: Khi người dùng truy cập địa chỉ IP của esp8266, webserver sẽ trả về trang web có giao diện điều khiển LED. Hàm xử lý yêu cầu này là handleRoot().
    • Yêu cầu bật LED: Khi người dùng truy cập địa chỉ IP/led/on, webserver sẽ bật LED và trả về thông báo “LED đã được bật”. Hàm xử lý yêu cầu này là handleLedOn().
    • Yêu cầu tắt LED: Khi người dùng truy cập địa chỉ IP/led/off, webserver sẽ tắt LED và trả về thông báo “LED đã được tắt”. Hàm xử lý yêu cầu này là handleLedOff().
    • Yêu cầu không hợp lệ: Khi người dùng truy cập một địa chỉ IP không tồn tại, webserver sẽ trả về mã lỗi 404. Hàm xử lý yêu cầu này là handleNotFound().
  • Bắt đầu webserver và in ra thông báo “Webserver started” trên cổng nối tiếp.
  • Ta cần đặt hàm server.handleClient() trong vòng lặp void loop() để lắng nghe yêu cầu từ phía người dùng.
//Hàm khởi tạo webserver
void setupServer() {
  //Thiết lập chân LED là output
  pinMode(LED_PIN, OUTPUT);
  //Tắt LED
  digitalWrite(LED_PIN, HIGH);

  //Kết nối wifi
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());//In địa chỉ IP kết nối ra serial monitor

  //Định nghĩa các hàm xử lý yêu cầu từ người dùng
  //Nếu người dùng truy cập địa chỉ IP của ESP8266, trả về giao diện web để điều khiển LED
  server.on("/", handleRoot);

  //Nếu người dùng truy cập địa chỉ IP/led/on, bật LED và trả về thông báo
  server.on("/led/on", handleLedOn);

  //Nếu người dùng truy cập địa chỉ IP/led/off, tắt LED và trả về thông báo
  server.on("/led/off", handleLedOff);

  //Nếu người dùng truy cập địa chỉ IP không hợp lệ, trả về mã lỗi 404
  server.onNotFound(handleNotFound);

  //Bắt đầu webserver
  server.begin();
  Serial.println("Webserver started");
}

Xử lý yêu cầu từ người dùng

Các hàm xử lý yêu cầu từ người dùng là các hàm được gọi khi webserver nhận được một yêu cầu từ người dùng. Mỗi hàm sẽ nhận một yêu cầu từ server và gửi lại một phản hồi cho người dùng. Phản hồi có thể là một chuỗi văn bản hoặc một chuỗi html.

//Hàm xử lý yêu cầu gốc
void handleRoot() {
  //Gửi biến chứa mã nguồn html cho người dùng
  server.send(200, "text/html", html);
}

//Hàm xử lý yêu cầu bật LED
void handleLedOn() {
  //Bật LED
  digitalWrite(LED_PIN, LOW);
  //Gửi thông báo cho người dùng
  server.send(200, "text/plain", "LED da duoc bat");
}

//Hàm xử lý yêu cầu tắt LED
void handleLedOff() {
  //Tắt LED
  digitalWrite(LED_PIN, HIGH);
  //Gửi thông báo cho người dùng
  server.send(200, "text/plain", "LED da duoc tat");
}

//Hàm xử lý yêu cầu không hợp lệ
void handleNotFound() {
  //Gửi mã lỗi 404 cho người dùng
  server.send(404, "text/plain", "Khong tim thay trang Web");
}
  • Hàm handleRoot(): Hàm này sẽ gửi lại biến chứa mã nguồn html cho người dùng, để hiển thị giao diện web điều khiển LED. 
  • Hàm handleLedOn(): Hàm này sẽ bật LED và gửi lại thông báo “LED đã được bật” cho người dùng. 
  • Hàm handleLedOff(): Hàm này sẽ tắt LED và gửi lại thông báo “LED đã được tắt” cho người dùng.
  • Hàm handleNotFound(): Hàm này sẽ gửi lại mã lỗi 404 cho người dùng khi yêu cầu không hợp lệ. 

Code điều khiển LED qua webserver trên esp8266 nodemcu

//Khai báo thư viện
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

//Khai báo thông tin wifi
const char* ssid = "Tên wifi của bạn";
const char* password = "Mật khẩu wifi của bạn";

//Khai báo đối tượng webserver, sử dụng port 80
ESP8266WebServer server(80);

//Khai báo chân LED
const int LED_PIN = 2;

//Khai báo biến chứa mã nguồn html dùng const char* R"html
const char* html = R"html(
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1" charset="utf-8">
    <style>
      button {
        width:200px;
        height:100px;
        font-size:36px;
      }
    </style>
  </head>
  <body>
    <h1>Webserver trên ESP8266</h1>
    <p>Điều khiển LED qua giao diện web</p>
    <p><a href="/led/on"><button>Bật LED</button></a></p>
    <p><a href="/led/off"><button>Tắt LED</button></a></p>
  </body>
</html>
)html";

//Hàm khởi tạo webserver
void setupServer() {
  //Thiết lập chân LED là output
  pinMode(LED_PIN, OUTPUT);
  //Tắt LED
  digitalWrite(LED_PIN, HIGH);

  //Kết nối wifi
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  //Định nghĩa các hàm xử lý yêu cầu từ người dùng
  //Nếu người dùng truy cập địa chỉ IP của ESP8266, trả về giao diện web để điều khiển LED
  server.on("/", handleRoot);

  //Nếu người dùng truy cập địa chỉ IP/led/on, bật LED và trả về thông báo
  server.on("/led/on", handleLedOn);

  //Nếu người dùng truy cập địa chỉ IP/led/off, tắt LED và trả về thông báo
  server.on("/led/off", handleLedOff);

  //Nếu người dùng truy cập địa chỉ IP không hợp lệ, trả về mã lỗi 404
  server.onNotFound(handleNotFound);

  //Bắt đầu webserver
  server.begin();
  Serial.println("Webserver started");
}

//Hàm xử lý yêu cầu gốc
void handleRoot() {
  //Gửi biến chứa mã nguồn html cho người dùng
  server.send(200, "text/html", html);
}

//Hàm xử lý yêu cầu bật LED
void handleLedOn() {
  //Bật LED
  digitalWrite(LED_PIN, LOW);
  //Gửi thông báo cho người dùng
  server.send(200, "text/plain", "LED da duoc bat");
}

//Hàm xử lý yêu cầu tắt LED
void handleLedOff() {
  //Tắt LED
  digitalWrite(LED_PIN, HIGH);
  //Gửi thông báo cho người dùng
  server.send(200, "text/plain", "LED da duoc tat");
}

//Hàm xử lý yêu cầu không hợp lệ
void handleNotFound() {
  //Gửi mã lỗi 404 cho người dùng
  server.send(404, "text/plain", "Khong tim thay trang Web");
}

//Hàm setup của Arduino IDE
void setup() {
  //Khởi tạo cổng nối tiếp
  Serial.begin(115200);
  //Khởi tạo webserver
  setupServer();
}

//Hàm loop của Arduino IDE
void loop() {
  //Xử lý các yêu cầu từ người dùng
  server.handleClient();
}
Expand

Sau khi nạp chương trình vào kít esp8266 nodemcu, bạn cần mở Serial Monitor trên Arduino IDE, với baudrate là 115200 sau đó ấn nút RST thì bạn sẽ nhìn thấy IP của esp8266 hiển thị.

Webserver trên esp8266

Bạn mở một trình duyệt web và truy cập vào IP trên, lưu ý thiết bị máy tính hoặc điện thoại của bạn phải kết nối chung mạng wifi với eps8266 thì mới truy cập được. Lúc này bạn có thể điều khiển bật tắt LED qua giao diện web rồi.

Webserver trên esp8266

Kết luận

Qua bài viết này mình đã hướng dẫn các bạn cách thiết lập một webserver căn bản trên esp8266. Để có thêm nhiều chức năng như: truyền nhận dữ liệu, cập nhật giá trị cảm biến lên giao diện web hoặc nhận dữ liệu từ phía người dùng bạn cần tìm hiểu thêm hai kỹ thuật là websocket ajax.

5/5 - (7 bình chọn)

2 Bình luận

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Chiêu sinh khóa Lập trình ESP32 căn bản, lớp (20h-21h30) 3-5-7 ngày 19/11/2024. Học phí 1tr/khóa (20 buổi). Đăng ký qua zalo: 0919.890.938

X
Contact Me on Zalo