What is a WebSocket?

What is a WebSocket: It's actually a very descriptive name defining the reason they are useful. You can imagine having two devices each with its own socket. You plug them together with a wire allowing direct instantaneous communication. In the case of a websocket, that wire is a virtual wire, created using software protocols.

what is a WebSocket

A websocket connects a client, (probably a browser) and server (could be an ESP32 chip), allowing real time instant bi-directional communication.

If you try out the examples of Arduino Web server code, you will see that the only way to get new sensor readings is to refresh the page.

When you want to see ESP32 sensor readings, you don't want to have to reload the page every time, and if you want updates every second, you definitely don't want to have to reload the page every time! For instance if you had a graph output you would want it to automatically scroll and show output.

WebSockets are additional protocols, to the existing protocols such as HTTP, providing an extra layer of communication that allows updates to elements of a page so you don't need to manually reload the page.

What is a WebSocket: Advantages of Websockets

In discussing "What is a WebSocket" its important to know that the older technology,that is still used in some cases, for bi-directional communication is AJAX. AJAX is based on existing technologies such as Javascript and XML/JSON. A WebSocket is a more recent protocol that is supported by modern web browsers, as well as some older versions released after 2011 when WebSockets were standardized.

Real-time data

You can transfer data between server and client instantly and you don't need polling or refreshing of the browser (client). For Arduino projects it means you can instantly control your lights (from browser to server - e.g. to an ESP32). It also means you get instant data back from the server e.g. reporting on temperature changes in a area.
imaginary arduino websockets

Efficiency

Once a websocket is established there is very low overhead in terms of network traffic. Because of the websocket there are no repeated HTTP requests - the protocol does not need to request a new connection for each transaction (this is the case when using AJAX - an older technique for bi-directional communication). In fact while I am writing this a websocket has been going for 90702 seconds updating that counter from an ESP32 every second.

Bi-directional communication

WebSockets allow you to implement simultaneous data exchange between the client and server. In the case of an Arduino Project you can control attached lights, and get back temperature data instantly. In the more general case you could use them for applications requiring instant responses or collaborative features.

Modern browser support

Most modern web browsers support WebSockets, ensuring compatibility across various platforms and devices. If you need to support older browsers then the AJAX system can be used but it is really not as good as websockets.

What is a WebSocket: How WebSockets work

To get a websocket going you write your html code using javascript to initiate a websocket startup process from the client (browser). The protocol is a handshake protocol where the client (browser) sends an HTTP request to the server (ESP32) requesting an upgrade to the WebSocket protocol.

On receipt of the upgrade request, and if the server supports WebSockets (you did remember to start a WebSocket in your Arduino code didn't you?) then the server responds with a status code of 101 (Switching protocols). This shows to the client that the connection has been upgraded successfully to a WebSocket.

From now on the client and server can send and receive data simultaneously i.e. a bi-directional communication link has been established.

What is a WebSocket: What code is needed?

When you write code for an ESP32 that implements a WebSocket, things can get complicated very fast, since all the code is stored in the ESP32. However you are going to have to write the following code:

  • For ESP32 (server) to browser (client) - in C/C++.
  • For browser (client) to ESP32 (server) - in Javascript.

The tricky bit is that both these sets of code have to be stored in the ESP32. So the ESP program operates the C/C++ code but sends the HTML code to the client to be executed in the client (browser).

So the ESP32 code has to contain the functions to drive the ESP32 side, but you also have to serve the HTML page containing:

  • The page text
  • CSS (Cascading Style Sheets) - to format the page.
  • Javascript to operate the WebSocket functionality.

You need to serve that page using an Arduino Web Server library.

Because both these sets of code exist on the ESP32 you need to take things slowly when developing code to avoid getting in a huge mess.

Other things to think about when developing the WebSocket code:

  1. When the client (browser) loads a web page on first load or refresh, the data from sensors and other sources doesn't update itself automatically - the act of getting the current values is not part of the web page code. This is due to the fact that the WebSocket won't update a value without explicit instructions from the C/C++ code i.e. you have to use the browser update action to force value updates in the C/C++ code that are then inserted in to the web page html.

    Remember to specifically retrieve data values (using the C/C++ code) and put them into the html page, when the web page is requested by the browser.

  2. If a web connection is lost you need to implement web reconnection code in javascript. For this you use the onclose member function and then create a new websocket again i.e. the same function you originally called to start the websocket.

  3. You have to remember that if an instance of a page is running in one browser there could be other instances in other browsers. So any updated value that will be sent to the ESP32 (server) must be broadcast to all, so that all browser instances show the same data. That means you have to code your handleWebSocketEvent function to react to incoming WebSocket data and the generate broadcast data messages - back to clients (browsers).

  4. Data transfer is probably best handled by using a JSON string formatted strings as this is a standard platform independent protocol,  widely used for data transfer. An example of JSON formatting is:

    {
      "label": "eepromValue",
      "value": 30, 
    }

    Because the string is simple, you don't need a JSON library. You can format the JSON data as a string quite simply (see below). When you want to transfer more complex data, the ArduinoJSON library is a good choice.

  5. Server (ESP32) to Client (Browser) :

    Here a code snippet example is shown for taking data value held EEPROM and transmitting it to be displayed in an entry box in the browser page.

    Server code (ESP32) : JSON transmit to Browser.

    // Create a JSON message containing the EEPROM value
    String eepromUpdateMsg = "{\"label\":\"eepromValue\",\"value\":\"" + eepromString + "\"}";

    webSocket.textAll(eepromUpdateMsg);

    Note: Here you don't need an Arduino JSON library as it is simply a string.

    Here the browser code accepts the WebSocket message and decodes its label, and updates the page if the label matches that sent from the ESP32 (here 'eepromValue').

    Client code (Browser) : javascript JSON decode with:

    webSocket.onmessage = function(event) {
            var data = JSON.parse(event.data);
            if (data.label === 'eepromValue') {
                    document.getElementById('inputData').value = data.value;
            }
            ...  // other if (data.label === <xyz>) actions.
    }

    The above javascript code updates an HTML text box with id 'inputData'.

    So the effect is that the ESP32 transmits a JSON string with a data value that then updates the HTML page with the new value, all done without page refresh.

  6. Client (Browser) to Server (ESP32):

    Pressing a button in the browser page causes javascript to retrieve the value held in a text box, and transmit that value as an EEPROM update message to the ESP32.

    Data transfer is again, best handled by using a javascript JSON parser as this is a standard information transfer protocol.

    Looking at the same text box (in the previous code) that contains an editable value that will be stored as the eepromValue in the ESP32. A separate button initiates the data transfer from the browser to the ESP32.

    Client code (Browser) : Javascript transmit WebSocket data

    Here the HTML code implements a button that when pressed ('onclick') calls the sendData function.

    The HTML code for the button that initiates the transfer will be:

    <button onclick='sendData()'>Send Data</button>

    When you click this button in the browser, the javascript function sendData() is called:

    function sendData() {
          var data = document.getElementById('inputData').value;
          webSocket.send(data);
    }

    Server code (ESP32) : WebSocket data decode

    ESP32 C/C++ code using a WebSocket library decodes the incoming message and updates the EEPROM location with the received data.

    The handleWebSocketEvent() function reacts to the data received over the WebSocket and takes appropriate action. In this case it programs the EEPROM.

    void handleWebSocketEvent( ...
        switch (type) {
        ...
        case WS_EVT_DATA:
             String payload = String((char*)data);
             int receivedData = payload.toInt();
     
             EEPROM.write(EEPROM_ADDRESS, receivedData);
             EEPROM.commit();

             // As mentioned. When ESP32 receives data it re-transmits to all.
             // Create a JSON message containing the EEPROM value
                String eepromUpdateMsg = "{\"label\":\"eepromValue\",\"value\":\"" + eepromString + "\"}";
             
              // Send the EEPROM value to all clients
              webSocket.textAll(eepromUpdateMsg); 

        ... more code.

        } // end case

You can see the essential data transmission aspects in the code above that allows simultaneous bi-directional communication using WebSockets.

Conclusions

Websockets provide powerful bi-directional communication which is essential for responsive systems. They allow you to control pins of an ESP32 (to control a relay etc). But they also allow data communication the other way e.g. for sensor readings.

All this is done without you having to refresh the browser.


Next: For A full tutorial on an ESP32 WebSocket Server click the link.


Written by John Main, who has a degree in Electronic Engineering.

Note: Parts of this page were written using chatgpt as a research assistant. Some images were created using leonardo.ai.




Comments

Have your say about what you just read! Leave me a comment in the box below.

Don’t see the comments box? Log in to your Facebook account, give Facebook consent, then return to this page and refresh it.



Privacy Policy | Contact | About Me

Site Map | Terms of Use