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.
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.
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.
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:
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.
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.
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).
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.
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').
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.
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();
// 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.
How to get accurate DHT22 digital humidity sensor readings with an Arduino. Did you know it also measures temperature as Well? Find out why, in this page...
A PIR sensor lets your Arduino sense movement without contact. This tutorial covers PIR sensor basics, connecting one to an Arduino board and coding a motion detector.
Arduino Hall Effect Sensor: Add magnetic sensing superpowers to your Arduino projects with an easy-to-use hall effect sensor. With full code and layout...
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.