ESP32 Arduino : Envoi de données avec le client socket

 

introduction

Dans ce tutoriel ESP32, nous verrons comment envoyer des données avec un client socket sur le noyau Arduino.

Puisque nous aurons besoin d'atteindre un serveur de socket, nous allons implémenter le nôtre en utilisant Python. Vous pouvez vérifier en détail comment configurer un serveur de socket en Python sur ce post précédent.

Les tests ont été effectués à l'aide d'un  module ESP32 de DFRobot  intégré dans une  carte de développement ESP32 .

 

Le code Python

Pour commencer, nous allons importer le module socket de Python , qui mettra à disposition les fonctions dont nous avons besoin pour définir le serveur de socket.

1
import socket

Après cela, nous créons un objet de classe socket , que nous utiliserons pour configurer le serveur et écouter les connexions entrantes.

1
s = socket.socket()

Maintenant que nous avons notre objet socket , nous devons le lier à une adresse IP et à un port. Ce seront les deux paramètres que notre client socket doit connaître pour atteindre le serveur.

Pour effectuer cette liaison, nous devons appeler la méthode bind sur notre objet socket , en passant en première entrée l'adresse IP, sous forme de chaîne, et en deuxième entrée le port, sous forme de nombre.

Puisque nous allons exposer le serveur à atteindre dans le réseau local, nous allons utiliser l' IP '0.0.0.0' , qui liera le socket à toutes les adresses IP de la machine. Plus tard, nous devrons découvrir quelle est l'adresse IP locale réelle de la machine, afin que nous puissions l'atteindre depuis le client.

Nous utiliserons le port 8090 dans ce code, mais vous pouvez essayer avec un autre port. Assurez-vous simplement que le port que vous allez utiliser est disponible et qu'il n'est pas déjà utilisé par une autre application.

1
s.bind(('0.0.0.0', 8090 ))

Après la liaison, nous devons faire en sorte que notre serveur commence à écouter les connexions. Nous le faisons en appelant la méthode listen sur l'objet socket.

Notez que cette méthode reçoit en entrée le nombre de connexions non acceptées qui sont autorisées avant de refuser de nouvelles connexions [1]. Étant donné que notre cas d'utilisation simple n'implique pas plusieurs clients, nous pouvons passer la valeur 0.

1
s.listen(0)

Pour commencer à recevoir les connexions réelles, nous devons appeler la méthode accept sur notre objet socket . Il s'agit d'une méthode bloquante, ce qui signifie que l'exécution du programme s'arrêtera jusqu'à ce qu'un nouveau client se connecte au serveur.

Une fois qu'un client se connecte au serveur, cette méthode renvoie une paire avec un nouvel objet socket et l'adresse du client. Nous pouvons alors utiliser ce nouvel objet socket pour établir la communication avec le client connecté.

Notez que puisque les sockets sont des mécanismes bidirectionnels, nous pouvons à la fois envoyer et recevoir des données.

En supposant que nous voulons que notre serveur fonctionne indéfiniment, nous effectuons cet appel de méthode accept dans une boucle infinie.

1
2
3
4
while True:
 
    client, addr = s.accept()
    # client handling code

Nous allons maintenant commencer à recevoir des données du client. Nous supposerons également que le client sera celui qui fermera la connexion après avoir envoyé toutes les données, nous lirons donc également les données à l'intérieur d'une boucle imbriquée, qui ne s'interrompra que lorsque le client se déconnectera.

Pour recevoir les données envoyées par le client, il suffit d'appeler la méthode recv sur l'objet socket renvoyé par la méthode accept précédemment appelée .

Notez que dans Python 3.x (celui que j'utilise pour ce tutoriel), la méthode recv renvoie les données sous la forme d'un objet bytes . D'autre part, sur Python 2.x, les données sont renvoyées sous forme de chaîne, donc si vous utilisez une ancienne version de Python, vous devez adapter votre code en conséquence.

En entrée, le recv reçoit le nombre maximum d'octets à recevoir à la fois. Si plus que le nombre spécifié d'octets sont envoyés par le client, ils peuvent être récupérés avec d'autres appels à la méthode recv .

Une chose importante à garder à l'esprit est que la méthode recv  est également bloquante. Ainsi, après avoir appelé cette méthode, l'exécution sera bloquée jusqu'à ce que le client envoie des données ou se déconnecte.

En cas de déconnexion, la méthode recv renverra un objet bytes vide, que nous pouvons utiliser comme condition d'arrêt pour la boucle de lecture des données.

1
2
3
4
5
6
7
8
9
dix
11
12
while True:
 
    client, addr = s.accept()
 
    while True:
        content = client.recv(32)
 
        if len(content) ==0:
           break
 
        else:
            print(content)

Enfin, lorsque le client se déconnecte, nous appelons la méthode close sur l'objet socket client  pour libérer les ressources et revenir à l'écoute d'une nouvelle connexion. Le code Python final peut être vu ci-dessous et inclut déjà cet appel.

1
2
3
4
5
6
7
8
9
dix
11
12
13
14
15
16
17
18
19
20
21
22
import socket
 
s = socket.socket()        
 
s.bind(('0.0.0.0', 8090 ))
s.listen(0)                
 
while True:
 
    client, addr = s.accept()
 
    while True:
        content = client.recv(32)
 
        if len(content) ==0:
           break
 
        else:
            print(content)
 
    print("Closing connection")
    client.close()


Le code Arduino

Dans le code Arduino, nous allons commencer à inclure la bibliothèque WiFi.h , afin que nous puissions nous connecter à un réseau WiFi, puis établir la connexion socket.

1
#include <WiFi.h>

En tant que variables globales, nous déclarerons les informations d'identification du réseau WiFi auquel nous allons nous connecter. Nous aurons besoin du nom du réseau (SSID) et du mot de passe.

1
2
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPass";

Nous déclarerons également comme variables globales l'adresse IP et le port du serveur de socket que nous avons implémenté en Python. Comme nous l'avons vu dans le code Python, nous n'avons pas lié le serveur à une adresse IP particulière, mais avons plutôt utilisé l' IP '0.0.0.0' , ce qui signifie que le serveur doit être disponible dans toutes les IP de cette machine.

Ainsi, nous devons déterminer l'adresse IP locale de la machine sur le réseau local, afin que nous puissions utiliser cette adresse IP sur le code Arduino. Le moyen le plus simple d'obtenir l'adresse IP consiste à taper la commande ipconfig sur la ligne de commande si vous êtes sous Windows, ou la commande ifconfig si vous êtes sous Linux. Ces commandes doivent être envoyées sur la machine qui exécutera le code Python. 

Notez que pour que l'ESP32 puisse atteindre le serveur Python hébergé sur un ordinateur, les deux appareils doivent être sur le même réseau puisque nous ne faisons aucune redirection de port et nous utilisons simplement des IP locales.

Alternativement, vous pouvez obtenir l'adresse IP locale de votre machine à partir de ce site Web.

Notez que dans le code ci-dessous, j'utilise l'adresse IP locale de mon ordinateur sur mon réseau local. Le vôtre sera probablement différent. Le port était 8090 , comme nous l'avons défini dans le code Python.

1
2
const uint16_t port = 8090;
const char * host = "192.168.1.83";

Passant à la fonction de configuration Arduino, nous allons simplement ouvrir une connexion série pour afficher les résultats de notre programme et nous occuper de la connexion au réseau WiFi, en utilisant les informations d'identification précédemment déclarées.

1
2
3
4
5
6
7
8
9
dix
11
12
13
14
15
void setup()
{
 
  Serial.begin(115200);
 
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("...");
  }
 
  Serial.print("WiFi connected with IP: ");
  Serial.println(WiFi.localIP());
 
}

Ensuite, sur la boucle Arduino, nous établirons périodiquement la connexion au serveur et lui enverrons des données.

Tout d'abord, nous déclarons un objet de classe  WiFiClient , que nous utiliserons pour établir la connexion et envoyer les données.

1
WiFiClient client;

Ensuite, pour établir la connexion proprement dite, nous devons appeler la méthode connect sur notre objet WiFiClient , en passant en première entrée l'IP du serveur et en deuxième le port.

Cette méthode renvoie 1 si la connexion a réussi et 0 sinon, nous pouvons donc l'utiliser pour effectuer une vérification des erreurs. En cas d'échec de la connexion, nous imprimons un message à la connexion série et attendons une seconde avant d'essayer de nous reconnecter.

1
2
3
4
5
6
7
if (!client.connect(host, port)) {
 
   Serial.println("Connection to host failed");
 
   delay(1000);
   return;
}

En cas de succès, nous passons à autre chose et envoyons les données réelles au serveur, ce qui se fait en appelant la méthode d' impression sur l' objet WiFiClient et en passant en entrée la chaîne à envoyer.

Notez qu'il existe d'autres méthodes que nous pouvons utiliser pour envoyer des données au serveur, telles que la méthode d' écriture  .

1
client.print("Hello from ESP32!");

Comme il s'agit d'un simple tutoriel d'introduction, nous n'attendrons pas de données du serveur, nous pouvons donc simplement terminer la connexion en appelant la méthode stop sur notre objet WiFiClient , libérant ainsi les ressources.

1
client.stop();

Le code source final est présenté ci-dessous. Il contient quelques impressions supplémentaires et un délai de 10 secondes entre chaque itération de la boucle Arduino.

1
2
3
4
5
6
7
8
9
dix
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <WiFi.h>
 
const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPass";
 
const uint16_t port = 8090;
const char * host = "192.168.1.83";
 
void setup()
{
 
  Serial.begin(115200);
 
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("...");
  }
 
  Serial.print("WiFi connected with IP: ");
  Serial.println(WiFi.localIP());
 
}
 
void loop()
{
    WiFiClient client;
 
    if (!client.connect(host, port)) {
 
        Serial.println("Connection to host failed");
 
        delay(1000);
        return;
    }
 
    Serial.println("Connected to server successful!");
 
    client.print("Hello from ESP32!");
 
    Serial.println("Disconnecting...");
    client.stop();
 
    delay(10000);
}


Tester le code

Pour tester l'ensemble du système, nous allons commencer par compiler et télécharger le code Arduino sur l'ESP32. Une fois la procédure terminée, ouvrez simplement le moniteur série Arduino IDE.

Vous devriez obtenir une sortie similaire à la figure 1. Étant donné que le serveur Python n'est pas encore en cours d'exécution, les tentatives de connexion doivent échouer.

ESP32 Arduino Socket Client échoue connection.png

Figure 1 – Sortie du programme lorsque le serveur de socket Python n'est pas connecté.

Ensuite, exécutez le code Python sur l'outil de votre choix. Dans mon cas, je l'exécute sur IDLE , l'IDE Python fourni avec l'installation du langage.

Une fois que le serveur est opérationnel, vous devriez commencer à recevoir les messages de l'ESP32, comme illustré à la figure 2.

Client Arduino Socket ESP32 vers programme Python.png

Figure 2 - Sortie du programme Python lors de la réception de données de l'ESP32.

Si vous revenez au moniteur série Arduino IDE, vous devriez commencer à voir les messages de connexion et de déconnexion que nous avons inclus dans notre code, comme illustré à la figure 3.

ESP32 Arduino Socket Client Atteindre le serveur Python.png

Figure 3 – Connexion réussie au serveur de socket Python sur l'ESP32.

 

Commentaires

Posts les plus consultés de ce blog

Comment fonctionne l'optimise d'Adam

RESEAU DE NEURONE CONVOLUTIF

Comment utiliser les diagrammes PlantUML dans Visual Studio Code pour Windows 10