ESP32 WebSocket

Trong hướng dẫn này, chúng ta sẽ tìm hiểu WebSocket là gì, tại sao cần sử dụng nó để điều khiển ESP32 một cách mượt mà, và cách sử dụng WebSocket với ESP32. Trong một ví dụ thực tế, chúng ta sẽ học cách tạo một ứng dụng chat giữa trình duyệt web và ESP32, cho phép bạn:

ESP32 websocket

Linh Kiện Cần Thiết

1×mô-đun phát triển ESP-WROOM-32
1×Alternatively, ESP32 Uno-form board
1×Alternatively, ESP32 S3 Uno-form board
1×Cáp USB Type-C
1×(Khuyến nghị) Screw Terminal Expansion Board for ESP32
1×(Khuyến nghị) Breakout Expansion Board for ESP32
1×(Khuyến nghị) Power Splitter for ESP32

Or you can buy the following kits:

1×DIYables ESP32 Starter Kit (ESP32 included)
1×DIYables Sensor Kit (30 sensors/displays)
1×DIYables Sensor Kit (18 sensors/displays)

ESP32 WebSocket là gì?

Bây giờ, bạn có thể hỏi, "WebSocket là gì?" Nó khá đơn giản: WebSocket là một công nghệ cho phép trình duyệt web giao tiếp trực tiếp với web server theo thời gian thực.

  • Không có WebSocket, bạn phải làm mới trang web để nhận được cập nhật. Điều đó không thuận tiện lắm.
  • Với WebSocket, trang web và server luôn kết nối. Điều này có nghĩa là chúng có thể chia sẻ thông tin ngay lập tức mà không cần tải lại trang.

Bạn có thể bắt gặp WebSocket trong các ứng dụng web hàng ngày như game online, tin nhắn tức thì, và cập nhật thị trường chứng khoán.

Tại sao chúng ta cần WebSocket để điều khiển ESP32 một cách mượt mà?

Hãy tưởng tượng bạn muốn điều khiển xe điều khiển từ xa bằng giao diện web trên điện thoại hoặc máy tính. Không có WebSocket, mỗi khi bạn muốn thay đổi hướng hoặc tốc độ của xe, bạn sẽ cần làm mới trang web. Giống như phải nhấn nút "tải lại" mỗi lần bạn muốn lệnh của mình đến được xe.

Bây giờ, với WebSocket, giống như có một kết nối liên tục và trực tiếp giữa điện thoại hoặc máy tính của bạn và xe. Bạn không còn cần làm mới trang mỗi khi muốn điều hướng xe hoặc điều chỉnh tốc độ. Giống như xe luôn lắng nghe lệnh của bạn theo thời gian thực, không có độ trễ nào do việc tải lại trang liên tục.

Nói chung, WebSocket cho phép bạn:

  • Gửi dữ liệu từ trình duyệt web đến ESP32 mà không cần tải lại trang web.
  • Gửi dữ liệu từ ESP32 đến trình duyệt web mà không cần tải lại trang web.

Điều này cho phép giao tiếp hai chiều theo cách thời gian thực.

Lợi ích của WebSocket với ESP32:

  • Điều Khiển Thời Gian Thực: WebSocket cho phép giao tiếp tức thì với ESP32, đảm bảo phản hồi nhanh chóng với các lệnh để có trải nghiệm người dùng mượt mà.
  • Kết Nối Liên Tục: Duy trì kết nối liên tục mà không cần làm mới trang điều khiển, tạo ra một đường giao tiếp luôn sẵn sàng cho các hướng dẫn ngay lập tức.
  • Hiệu Quả: Trải nghiệm phản hồi nhanh chóng mà không cần tải lại trang liên tục, nâng cao sự thích thú và hiệu quả tổng thể của người dùng.

Web Chat với ESP32 qua WebSocket

Nội dung trang web (HTML, CSS, JavaScript) được lưu trữ riêng biệt trong file index.h. Vì vậy, chúng ta sẽ có hai file code trên Arduino IDE:

  • Một file .ino là code ESP32, tạo web server và WebSocket server
  • Một file .h, chứa nội dung của trang web.

Các Bước Nhanh

  • Nếu đây là lần đầu tiên bạn sử dụng ESP32, hãy xem ESP32 - Cài Đặt Phần Mềm.
  • Kết nối board ESP32 với PC qua cáp micro USB
  • Mở Arduino IDE trên PC.
  • Chọn đúng board ESP32 (ví dụ ESP32 Dev Module) và cổng COM.
  • Mở Library Manager bằng cách nhấp vào biểu tượng Library Manager trên thanh điều hướng bên trái của Arduino IDE.
  • Tìm kiếm "DIYables ESP32 WebServer", sau đó tìm thư viện Web Server được tạo bởi DIYables.
  • Nhấp nút Install để cài đặt thư viện Web Server.
ESP32 web server thư viện
  • Trên Arduino IDE, tạo sketch mới, Đặt tên cho nó, ví dụ newbiely.com.ino
  • Sao chép code dưới đây và mở bằng Arduino IDE
/* * Mã ESP32 này được phát triển bởi newbiely.vn * Mã ESP32 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/esp32/esp32-websocket */ #include <DIYables_ESP32_WebServer.h> #include "index.h" // WiFi credentials const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; // Create web server instance DIYables_ESP32_WebServer server; DIYables_ESP32_WebSocket* webSocket; // Web Page handlers void handleHome(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { // HTML_CONTENT from the index.h file server.sendResponse(client, HTML_CONTENT); } // WebSocket event handlers void onWebSocketOpen(net::WebSocket& ws) { Serial.println("New WebSocket connection"); // Send welcome message const char welcome[] = "Connected to ESP32 WebSocket Server!"; } void onWebSocketMessage(net::WebSocket& ws, const net::WebSocket::DataType dataType, const char* message, uint16_t length) { Serial.print("WebSocket Received ("); Serial.print(length); Serial.print(" bytes): "); Serial.println(message); // Broadcast response to all connected clients using the library if (webSocket != nullptr) { String response = "Received: " + String((char*)message); webSocket->broadcastTXT(response); Serial.print("WebSocket sent ("); Serial.print(response.length()); Serial.print(" bytes): "); Serial.println(response); } } void onWebSocketClose(net::WebSocket& ws, const net::WebSocket::CloseCode code, const char* reason, uint16_t length) { Serial.println("WebSocket client disconnected"); } void setup() { Serial.begin(9600); delay(1000); Serial.println("ESP32 Web Server and WebSocket Server"); // Configure web server routes server.addRoute("/", handleHome); // Start web server with WiFi connection server.begin(WIFI_SSID, WIFI_PASSWORD); // Enable WebSocket functionality webSocket = server.enableWebSocket(81); if (webSocket != nullptr) { // Set up WebSocket event handlers webSocket->onOpen(onWebSocketOpen); webSocket->onMessage(onWebSocketMessage); webSocket->onClose(onWebSocketClose); } else { Serial.println("Failed to start WebSocket server"); } } void loop() { // Then handle HTTP requests server.handleClient(); // Handle WebSocket server.handleWebSocket(); }
  • Sửa đổi thông tin WiFi (SSID và password) trong code để khớp với thông tin đăng nhập mạng của bạn.
  • Tạo file index.h trên Arduino IDE bằng cách:
    • Nhấp vào nút ngay dưới biểu tượng serial monitor và chọn New Tab, hoặc sử dụng phím Ctrl+Shift+N.
    Arduino ide 2 adds file
    • Đặt tên file là index.h và nhấp nút OK
    Arduino ide 2 adds file index.h
    • Sao chép code dưới đây và dán vào index.h.
    /* * Mã ESP32 này được phát triển bởi newbiely.vn * Mã ESP32 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/esp32/esp32-websocket */ const char *HTML_CONTENT = R"=====( <!DOCTYPE html> <!-- saved from url=(0019)http://192.168.0.2/ --> <html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> <title>ESP32 WebSocket</title> <meta name="viewport" content="width=device-width, initial-scale=0.7"> <link rel="icon" href="https://diyables.io/images/page/diyables.svg"> <style> /* Add some basic styling for the chat window */ body { font-size: 16px; } .chat-container { width: 400px; margin: 0 auto; padding: 10px; } .chat-messages { height: 250px; overflow-y: auto; border: 1px solid #444; padding: 5px; margin-bottom: 5px; } .user-input { display: flex; margin-bottom: 20px; } .user-input input { flex: 1; border: 1px solid #444; padding: 5px; } .user-input button { margin-left: 5px; background-color: #007bff; color: #fff; border: none; padding: 5px 10px; cursor: pointer; } .websocket { display: flex; align-items: center; margin-bottom: 5px; } .websocket button { background-color: #007bff; color: #fff; border: none; padding: 5px 10px; cursor: pointer; } .websocket .label { margin-left: auto; } </style> <script> var ws; var wsm_max_len = 4096; /* bigger length causes uart0 buffer overflow with low speed smart device */ function update_text(text) { var chat_messages = document.getElementById("chat-messages"); chat_messages.innerHTML += text + '<br>'; chat_messages.scrollTop = chat_messages.scrollHeight; } function send_onclick() { if(ws != null) { var message = document.getElementById("message").value; if (message) { document.getElementById("message").value = ""; ws.send(message + "\n"); update_text('<span style="color:navy">' + message + '</span>'); // You can send the message to the server or process it as needed } } } function connect_onclick() { if(ws == null) { ws = new WebSocket("ws://" + window.location.host + ":81"); document.getElementById("ws_state").innerHTML = "CONNECTING"; ws.onopen = ws_onopen; ws.onclose = ws_onclose; ws.onmessage = ws_onmessage; } else ws.close(); } function ws_onopen() { document.getElementById("ws_state").innerHTML = "<span style='color:blue'>CONNECTED</span>"; document.getElementById("bt_connect").innerHTML = "Disconnect"; document.getElementById("chat-messages").innerHTML = ""; } function ws_onclose() { document.getElementById("ws_state").innerHTML = "<span style='color:gray'>CLOSED</span>"; document.getElementById("bt_connect").innerHTML = "Connect"; ws.onopen = null; ws.onclose = null; ws.onmessage = null; ws = null; } function ws_onmessage(e_msg) { e_msg = e_msg || window.event; // MessageEvent console.log(e_msg.data); update_text('<span style="color:blue">' + e_msg.data + '</span>'); } </script> </head> <body> <div class="chat-container"> <h2>ESP32 WebSocket</h2> <div class="websocket"> <button class="connect-button" id="bt_connect" onclick="connect_onclick()">Connect</button> <span class="label">WebSocket: <span id="ws_state"><span style="color:blue">CLOSED</span></span></span> </div> <div class="chat-messages" id="chat-messages"></div> <div class="user-input"> <input type="text" id="message" placeholder="Type your message..."> <button onclick="send_onclick()">Send</button> </div> <div class="sponsor">Sponsored by <a href="https://amazon.com/diyables">DIYables</a></div> </div> </body></html> )=====";
    • Bây giờ bạn có code trong hai file: newbiely.com.inoindex.h
    • Nhấp nút Upload trên Arduino IDE để upload code lên ESP32.
    • Mở Serial Monitor
    • Kiểm tra kết quả trên Serial Monitor.
    COM6
    Send
    Connecting to WiFi... Connected to WiFi ESP32 Web Server's IP address IP address: 192.168.0.2
    Autoscroll Show timestamp
    Clear output
    9600 baud  
    Newline  
    • Ghi nhớ địa chỉ IP được hiển thị, và nhập địa chỉ này vào thanh địa chỉ của trình duyệt web trên smartphone hoặc PC.
    • Bạn sẽ thấy trang web như bên dưới:
    ESP32 websocket web browser
    • Nhấp nút CONNECT để kết nối trang web với ESP32 qua WebSocket.
    • Gõ một vài từ và gửi chúng đến ESP32.
    • Bạn sẽ thấy phản hồi từ ESP32.
    ESP32 websocket chat server

    ※ Lưu ý:

    • Nếu bạn sửa đổi nội dung HTML trong index.h và không chạm vào bất cứ thứ gì trong file newbiely.com.ino, khi bạn compile và upload code lên ESP32, Arduino IDE sẽ không cập nhật nội dung HTML.
    • Để làm cho Arduino IDE cập nhật nội dung HTML trong trường hợp này, hãy thực hiện thay đổi trong file newbiely.com.ino (ví dụ thêm dòng trống, thêm comment....)

    Giải Thích Code Từng Dòng

    Code ESP32 ở trên có giải thích từng dòng. Vui lòng đọc các comment trong code!

Cách Hệ Thống Hoạt Động

Code ESP32 hoạt động bằng cách tạo cả web server và WebSocket Server. Quy trình diễn ra như sau:

  • Khi bạn nhập địa chỉ IP của ESP32 vào trình duyệt web, một yêu cầu được thực hiện cho trang web (Giao Diện Người Dùng) từ ESP32.
  • Web server của ESP32 phản hồi bằng cách truyền nội dung của trang web (HTML, CSS, JavaScript).
  • Sau đó, trình duyệt web của bạn hiển thị trang web.
  • Khi bạn nhấp nút CONNECT, code JavaScript nhúng trong trang web thiết lập kết nối WebSocket đến WebSocket server trên ESP32.
  • Với kết nối WebSocket được thiết lập, khi bạn gõ gì đó và nhấp nút SEND, code JavaScript gửi văn bản đó đến ESP32 thông qua kết nối WebSocket ở chế độ nền.
  • Khi nhận được giá trị góc, WebSocket server gửi lại phản hồi đến trang web.

Bạn có thể học các ví dụ ESP32 WebSocket khác dưới đây: