WebSocket communication with an ESP8266 or Arduino in Python. Test with the ws4py library on Raspberry Pi

The Websocket is a much faster communication protocol than the REST protocol that uses standard HTTP requests. The Websocket allows to open a bi-directional communication channel between two devices. In this case, it will be between an ES8266 (but it could also be an Arduino or ESP32) and a Raspberry Pi 3. In this tutorial, we will start a WebScoket server on an ESP8266 (Wemos d1 R2). The client will be developed in Python and will be hosted on a Raspberry Pi. We will re-use this architecture very soon to drive a robot arm in WiFi using a Gamepad (in the previous article, we saw how to intercept the shares).

The advantages of Websocket compared to the classic HTTP REST API

The websocket has been developed for applications that require quick or interactive answers. HTTP was developed in the prehistory of the Web (by CERN Geneva). The HTTP protocol is used to make the internet sites work but also the mobile applications (for example). REST APIs are also based on HTTP. HTTP is not suitable for applications that require quick or interactive responses. Indeed, every time the client makes a request to the server, we must open a connection, wait for the response from the server and close the connection which is resource-consuming and takes time to process.

We will not take into account the Ajax technology that allows the content of a web page to be updated asynchronously. Ajax can be used in Arduino / ESP8266 projects (and equivalent) on the web client side, ie in the HTML interface of the project (read these articles to find out more). An example of realization here.

The Websocket aims to solve these problems. The Websocket opens a communication tunnel between two devices. This tunnel remains open until the client disconnects. At any time the client can send messages (JSON, binary, text …) and vice versa.

Source : https://www.pubnub.com/blog/2015-01-05-websockets-vs-rest-api-understanding-the-difference/

 

To summarize, the Websocket has the following advantages:

  • Bi-directional: The HTTP protocol is unidirectional, ie the client sends a request to which the server responds. The customer then consumes the answer and so on. WebSocket is a bidirectional protocol in which there are no predefined message templates such as request / response. The client or server can send a message to the other party.
  • Full-duplex: server and client can send messages at any time regardless of current processes.
  • Single TCP Connection: Typically, a new TCP connection is started for an HTTP request and ends after the response is received. A new TCP connection must be established for another HTTP request / response. With the WebSocket, the client and the server communicate on the same TCP connection until the client or server closes the connection.
  • Lightweight: the Websocket focuses on the essential unlike the HTTP which loads a lot of information to each question / answer
    In terms of performance, the Websocket is much faster as shown in this study by developer Arun Gupta in 2014. Arun measured the time needed to send packets of messages. Each message weighs 1000 bytes.
websocket rest messages comparison speed

Source : http://blog.arungupta.me/rest-vs-websocket-comparison-benchmarks/

The difference may seem insignificant (30% faster) for a very small number of messages. You will see that to control a robotic arm or LED lighting from a mobile application, the difference is really significant!

Source : http://blog.arungupta.me/rest-vs-websocket-comparison-benchmarks/

Installing the Websocket library for ESP8266 on the Aduino IDE
By doing a search on the websocket keyword from the library manager, there are several libraries compatible with ESP8266 modules. However, I advise you to use the bookstore developed by Markus Sattler. It can start a server or turn the ESP8266 into a Websocket client. It is available on GitHub here. It is compatible with the following cards (damage, it is not compatible with the ESP32):

  • Arduino
  • ESP8266
  • ESP31B
  • Particle with STM32 ARM Cortex M3
  • ATmega328
  • ATmega2560

Start a Websocket server on an ESP8266 (also works on Arduino and ESP32)

The Websocket library contains several examples (client, server). This bookstore is very well done. It allows to connect a callback function that will be called each time a message is received. It is then very easy to connect the associated processing by decoding the messages (we will see how to do in the next paragraph).

We start by creating an object that will contain the Websocket server

In the setup, we start the server and we indicate the callback procedure that will be called for each new message.

The library allows to know the type of message received:

  • WStype_DISCONNECTED, the client has disconnected
  • WStype_CONNECTED, a customer just signed in
  • WStype_TEXT, a message of type text (string, JSON ..) has just arrived
  • WStype_BIN, a binary message has just arrived

Finally, we add as for a web server, updating the server each passage in the loop loop. It is better not to put delay in this loop to not slow down the server and therefore the receipt of messages.

Create a new sketch and paste the code below by changing the WiFi settings.

How to decode WebSocket messages

It is possible to send a message in JSON format and to decode it with the ArduinoJSON library presented previously in this article for example. However, this library is problematic when you receive a very large number of messages. To control the light intensity of a PWM LED or the position of a servomotor, it is best to split the message using more conventional functions that require less resources on the ESP8266. For example, we could use the C++ substring function (position, number of characters). Here, we get the first message (payload [0]) and we extract the identifier of the LED and the intensity. The separator used is “:”, which gives a message of the type led0:58.

Then, it is better to test the presence of a string rather than doing a test of equality between two chains (==).

Websocket client in Python with the ws4py library

There are several Python libraries for setting up Websocket communication. Here are the main ones you can use in your projects:

  • websockets 4.x. This is the best known, the documentation is here.
  • ws4py is a library developed by Sylvain Hellegouarch (Lawouach on GitHub). It is available on GitHub here. It is referenced on PyPi, so very easy to install and update with the pip command. The documentation is here.

Here, I propose you to use ws4py which is quite well documented and which supports very well the use of the threads under Python (tasks realized in parallel independently of the main program). Start by installing the ws4py library by running the following command

Ici, on va créer en client Websocket. Pour cela, on va importer la classe WebSocketClient de la librairie ws4py.

The ws4py library exposes several callback methods that can be used to trigger processing in the code. The following methods are available:

  • opened
  • closed
  • received_message

The ws4py documentation gives an example of use. We create a DummyClient of type WebSocketClient that contains the different states of the client.

Next, we create a websocket object by passing it the websocket server ip address. For the moment, we will communicate without security on the port 81. The address of a server is composed of the prefix ws:// or wss:// if it is secured by an SSL certificate (it is not the case here). Then we find the IP address of the server, in this case it is the IP address of the ESP8266. Finally, the port, here 81. This gives for example

Finally, we open the communication with the server

The ws.send (message) command sends a message to the server at any time. Messages from the server will be processed by the DummyClient using the received_message method. Any type of data can be sent. A character string with any data separator (|: -,), a JSON (for this we can use the JSON package for python), binary data (an image for example) …

Websocket client, full code in Python

Create a new script with the nano command wsled.py (for example) and paste the complete code below. Change the IP address of the ESP8266. Save the script with CTRL + X then Y.

Connect an LED between pin D7 (GPIO15) and GND. Add a resistor according to the voltage allowable by the LED (more info here). Upload the Arduino script to the ESP8266 and wait for it to connect to the WiFi network by opening the serial monitor. As soon as ESP is connected to the network, you can start the script with the python wsled.py  command. You can monitor the reception and decoding of messages on the serial monitor. You can change the publication speed of the client side (python script) by changing the waiting time. Here, it is .10 or 100ms (in python, the duration of the time.sleep function is indicated in seconds). You can pause the script at any time with the CTRL + C key combination.

That’s it, everything is in place for the project of piloting robotic arms with the help of a Gamepad!

Subscribe to the weekly newsletter

No spam and no other use will be made of your email. You can unsubscribe anytime.

  • Anthony Barnett

    Great tutorial and works even though I am a complete novice to all of this. Working on a Nodemcu apart from I have an exception error I need to track down – Exception (28):

    Just to let you know a couple of your prints are missing the ( )

DIY Projects