DIYables ESP32 Web Server With WebSocket Example

WebServerWithWebSocket Example - Real-Time Communication

Overview

This example demonstrates how to create an advanced multi-page web server with real-time WebSocket communication on ESP32, enabling bidirectional data exchange between the browser and ESP32.

Features

  • Real-time WebSocket communication for instant bidirectional messaging
  • Simple string-based commands (ping, hello, time, led on/off)
  • LED control via WebSocket commands
  • Built-in HTTP server serving WebSocket test interface
  • Echo functionality for testing message transmission
  • Connection status monitoring with automatic reconnection

Hardware Used In This Tutorial

1×ESP-WROOM-32 Dev Module
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×Recommended: Screw Terminal Expansion Board for ESP32
1×Recommended: Breakout Expansion Board for ESP32
1×Recommended: 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)
Disclosure: Some of the links in this section are Amazon affiliate links, meaning we may earn a commission at no additional cost to you if you make a purchase through them. Additionally, some links direct you to products from our own brand, DIYables .

Library Installation

Follow these instructions step by step:

  • If this is your first time using the ESP32, refer to the tutorial on setting up the environment for ESP32 in the Arduino IDE.
  • Connect the ESP32 board to your computer using a USB cable.
  • Launch the Arduino IDE on your computer.
  • Select the appropriate ESP32 board (e.g., ESP32) and COM port.
  • Open the Library Manager by clicking on the Library Manager icon on the left side of the Arduino IDE.
  • Search for Web Server for ESP32 and locate the mWebSockets by DIYables.
  • Click on the Install button to add the mWebSockets library.
ESP32 Web Server library

WebSocket Example

  • On Arduino IDE, Go to File Examples Web Server for ESP32 WebServerWithWebSocket example to open the example code

Code Structuree

The project consists of two main files:

  1. websocket_html.h:

Contains the HTML, CSS, and JavaScript code for the web interface. This file defines the user interface for interacting with the ESP32 via WebSocket, including buttons for sending commands, a message log, and connection status indicators.

  1. WebServerWithWebSocket.ino:

Implements the main server logic on the ESP32. This file sets up the HTTP and WebSocket servers, manages WiFi connectivity, processes incoming WebSocket messages, and controls hardware (such as the built-in LED) based on received commands.

Circuit Connection

No external components required - this example uses the built-in LED on pin 13.

WebSocket Communication

Connection Details

  • Web Server Port: 80 (HTTP)
  • WebSocket Port: 81 (WebSocket)
  • Protocol: RFC 6455 compliant WebSocket

Message Types

The actual implementation uses simple string commands:

  • Ping: "ping" → Response: "pong"
  • Greeting: "hello" → Response: "Hello from ESP32!"
  • Uptime: "time" → Response: "Uptime: X seconds"
  • LED Control: "led on" / "led off" → Response: "LED ON" / "LED OFF"
  • Echo: Any other text → Response: "Echo: [your message]"

Setup Instructions

1. Network Configuration

Edit the WiFi credentials directly in the WebServerWithWebSocket.ino file:

const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";

2. Upload Code and Monitor Output

  • Connect your ESP32 to your computer
  • Select the correct board and port in Arduino IDE
  • Upload the WebServerWithWebSocket.ino sketch
  • Open Serial Monitor (9600 baud)
  • Wait for WiFi connection
  • Note both HTTP and WebSocket server addresses
  • If you do not see IP address in Serial monitor, press the reset button on the ESP32 board
  • Open a web browser and enter the ESP32's IP address in the address bar (e.g., http://192.168.x.x/). You will see the web interface look like the below:
ESP32 WebSocket interface
  • Click "Connect" button to connect the web to the ESP32 via WebSocket.
  • Once the connection status shows "Connected", click each button one by one to test bidirectional communication between the web interface and ESP32 via WebSocket. The result will be as below:
ESP32 WebSocket Demo

Web Interface Features

The HTML interface (from websocket_html.h) provides:

  • WebSocket connection management with connect/disconnect buttons
  • Simple command buttons for ping, hello, time, LED on/off
  • Message input field for sending custom commands
  • Real-time message history showing sent and received messages
  • Connection status indicator showing WebSocket state

Code Explanation

WebSocket Server Setup

#include <DIYables_ESP32_WebServer.h> #include "websocket_html.h" // LED configuration #define LED_PIN 2 // ESP32 built-in LED pin // Server configuration WiFiServer httpServer(80); constexpr uint16_t wsPort = 81; WebSocketServer wss{wsPort}; void setup() { Serial.begin(9600); delay(1000); // Initialize built-in LED pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); // Connect to WiFi manually Serial.print("Connecting to "); Serial.println(WIFI_SSID); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } // Start HTTP server httpServer.begin(); // Configure WebSocket server with lambda handlers wss.onConnection([](WebSocket &ws) { Serial.println("New WebSocket connection"); // Set up message handler ws.onMessage([](WebSocket &ws, const WebSocket::DataType dataType, const char *message, uint16_t length) { handleWebSocketMessage(ws, message, length); }); // Send welcome message const char welcome[] = "Connected to ESP32!"; ws.send(WebSocket::DataType::TEXT, welcome, strlen(welcome)); }); // Start WebSocket server wss.begin(); }

WebSocket Message Handling

void handleWebSocketMessage(WebSocket &ws, const char *message, uint16_t length) { Serial.print("[WebSocket] Received ("); Serial.print(length); Serial.print(" bytes): "); Serial.println(message); String msgStr = String(message); String response = ""; // Command processing with simple string matching if (msgStr.equalsIgnoreCase("ping")) { response = "pong"; } else if (msgStr.equalsIgnoreCase("hello")) { response = "Hello from ESP32!"; } else if (msgStr.equalsIgnoreCase("time")) { response = "Uptime: " + String(millis()/1000) + " seconds"; } else if (msgStr.equalsIgnoreCase("led on")) { digitalWrite(LED_PIN, HIGH); response = "LED ON"; } else if (msgStr.equalsIgnoreCase("led off")) { digitalWrite(LED_PIN, LOW); response = "LED OFF"; } else { response = "Echo: " + msgStr; } // Send response ws.send(WebSocket::DataType::TEXT, response.c_str(), response.length()); }

Main Loop with WebSocket Processing

void loop() { // Handle HTTP requests WiFiClient httpClient = httpServer.available(); if (httpClient) { handleHTTPClient(httpClient); } // Handle WebSocket connections wss.listen(); delay(10); } // HTTP request handler void handleHTTPClient(WiFiClient client) { String request = ""; // Read HTTP request while (client.connected() && client.available()) { String line = client.readStringUntil('\n'); if (line == "\r") break; if (request.length() == 0) request = line; } // Serve web page or 404 if (request.indexOf("GET / HTTP") >= 0) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println(); client.print(htmlPage); } else { client.println("HTTP/1.1 404 Not Found"); client.println("Connection: close"); client.println(); } client.stop(); }

JavaScript WebSocket Client

Connection Management

let websocket; let isConnected = false; function initWebSocket() { const wsUrl = `ws://${window.location.hostname}:81/`; websocket = new WebSocket(wsUrl); websocket.onopen = function(event) { console.log('WebSocket connected'); isConnected = true; updateConnectionStatus('Connected'); }; websocket.onmessage = function(event) { handleWebSocketMessage(JSON.parse(event.data)); }; websocket.onclose = function(event) { console.log('WebSocket disconnected'); isConnected = false; updateConnectionStatus('Disconnected'); // Auto-reconnect after 3 seconds setTimeout(initWebSocket, 3000); }; websocket.onerror = function(error) { console.error('WebSocket error:', error); updateConnectionStatus('Error'); }; }

Message Handling

function handleWebSocketMessage(event) { const message = event.data; console.log('Received:', message); // Handle simple string responses (matching actual implementation) if (message === 'pong') { console.log('Ping response received'); addMessageToHistory('Received: pong'); } else if (message.startsWith('Hello from ESP32')) { addMessageToHistory('Received: ' + message); } else if (message.startsWith('Uptime:')) { updateUptimeDisplay(message); addMessageToHistory('Received: ' + message); } else if (message === 'LED ON' || message === 'LED OFF') { updateLedStatus(message); addMessageToHistory('Received: ' + message); } else if (message.startsWith('Echo:')) { addMessageToHistory('Received: ' + message); } else { addMessageToHistory('Received: ' + message); } }

Sending Commands

// Simple string-based command sending (matching actual implementation) function sendCommand(command) { if (isConnected) { websocket.send(command); addMessageToHistory('Sent: ' + command); } else { alert('WebSocket not connected!'); } } function controlLED(action) { if (action === 'on') { sendCommand('led on'); } else if (action === 'off') { sendCommand('led off'); } } function sendPing() { sendCommand('ping'); } function sendHello() { sendCommand('hello'); } function getUptime() { sendCommand('time'); }

HTML Interface Features

WebSocket Test Interface

The included HTML page provides a complete WebSocket testing interface:

  • Connection controls with connect/disconnect functionality
  • Quick command buttons for common commands (ping, hello, time, LED control)
  • Message input field for sending custom text commands
  • Real-time message log showing all communication
  • Connection status display with visual indicators

Built-in JavaScript Functions

The HTML interface includes JavaScript functions matching the ESP32 command structure:

// Send simple string commands to ESP32 function sendQuick(msg) { if (connected && ws) { ws.send(msg); addMsg('You: ' + msg, 'sent'); } else { addMsg('Not connected!'); } } // Handle WebSocket events ws.onmessage = function(event) { console.log('WebSocket message received:', event.data); addMsg('ESP32: ' + event.data, 'received'); };

Implementation Notes

Simplified Architecture

The actual implementation uses a basic approach:

  • Separate servers: WiFiServer for HTTP and WebSocketServer for WebSocket
  • Manual WiFi connection: Standard WiFi.begin() setup without integrated server management
  • String-based messaging: Simple string commands instead of JSON protocols
  • Lambda handlers: WebSocket event handlers defined as inline lambda functions
  • Basic HTML serving: Direct client.print() of HTML content from header file

Limitations of Current Implementation

  • No sensor data streaming (as shown in documentation examples)
  • No JSON message parsing
  • No broadcasting to multiple clients
  • No connection management beyond basic connect/disconnect
  • No heartbeat or keepalive system
  • No message queuing or reliability features

Available Commands

The working commands in the actual implementation:

  • pingpong
  • helloHello from ESP32!
  • timeUptime: X seconds
  • led onLED ON (turns on LED_PIN)
  • led offLED OFF (turns off LED_PIN)
  • Any other text → Echo: [your message]

Troubleshooting

Common Issues

WebSocket Connection Failed

  • Check if WebSocket port (81) is accessible
  • Verify firewall settings don't block port 81
  • Use browser developer tools to check WebSocket errors
  • Ensure ESP32 IP address is correct

Messages Not Received

  • Check Serial Monitor for WebSocket events and message reception
  • Verify command strings match exactly (case-insensitive)
  • Test with simple commands like "ping" first

LED Not Responding

  • Confirm LED_PIN is properly defined for your ESP32 board (typically GPIO 2)
  • Check Serial Monitor for command processing messages
  • Verify "led on" and "led off" commands are sent exactly

Debug Commands

Use these commands to test WebSocket functionality:

  • ping - Simple connectivity test
  • hello - Greeting response test
  • time - ESP32 uptime test
  • led on / led off - Hardware control test
  • Any other text will echo back for communication testing

Real-World Applications

Basic IoT Control

The current simple implementation is suitable for:

  • Remote LED control for basic device status indication
  • Simple command/response systems for device interaction
  • WebSocket connectivity testing for development purposes
  • Basic real-time communication demonstrations

Potential Enhancements

To extend this example for production use, consider adding:

  • JSON message parsing for structured data
  • Sensor data streaming capabilities
  • Multiple client connection management
  • Authentication and security features
  • Error handling and reconnection logic

Next Steps

  • Add JSON message parsing using ArduinoJson library
  • Integrate actual sensors (temperature, humidity, etc.)
  • Implement broadcasting to multiple WebSocket clients
  • Add authentication for secure access
  • Create mobile app interfaces using WebSocket connections

※ OUR MESSAGES