ESP32 Arduino : Configuration d'un serveur de socket
L'objectif de cet article est d'expliquer comment créer un serveur de socket simple sur l'ESP32, en utilisant le cœur Arduino. Les tests de ce tutoriel ESP32 ont été réalisés à l'aide d'un appareil ESP-WROOM-32 de DFRobot intégré dans une carte ESP32 FireBeetle .
Introduction
L'objectif de cet article est d'expliquer comment créer un serveur de socket simple sur l'ESP32, en utilisant le cœur Arduino. Il agira comme un serveur d'écho qui renverra au client tout contenu qu'il envoie.
Afin de tester notre serveur, nous allons développer un client socket Python très simple. La version Python utilisée était la 2.7 et le code a été testé sur Windows 8.
Les tests de ce tutoriel ESP32 ont été réalisés à l'aide d'un appareil ESP-WROOM-32 de DFRobot intégré dans une carte ESP32 FireBeetle .
Le code Python
Nous allons commencer notre code en important le module socket Python , qui nous permettra de nous connecter au serveur ESP32.
1 | import socket |
Ensuite, nous allons créer un objet de classe socket , qui possède les méthodes nécessaires pour se connecter au serveur.
1 | sock = socket.socket() |
Pour se connecter au serveur, nous aurons besoin de connaître à la fois son adresse IP et le port sur lequel il écoute les connexions entrantes. Nous stockerons les deux valeurs dans deux variables.
Pour le port, nous utiliserons 80 (nous le mettrons à la même valeur sur le code Arduino).
Pour l'IP, nous devrons utiliser celle attribuée à notre ESP32 lors de la connexion au réseau WiFi. Si vous ne connaissez pas l'adresse IP locale de votre ESP32 lorsqu'il se connecte à votre réseau, vous pouvez utiliser une valeur factice pour l'instant, car nous imprimerons plus tard sa valeur sur le code Arduino.
1 2 | host = "192.168.1.78" port = 80 |
Pour effectuer la connexion proprement dite, nous allons maintenant appeler la méthode connect sur notre objet socket et passer en entrée un tuple avec l'hôte et le port.
1 | sock.connect((host, port)) |
Étant donné que l'ESP32 agira comme un serveur d'écho, nous lui enverrons un message, puis nous récupérerons le résultat. Pour envoyer un message au serveur, nous allons simplement appeler la méthode send de l'objet socket et passer en entrée le contenu. Dans ce cas, nous enverrons un simple message "hello world".
1 2 | message = "Hello World" sock.send(message) |
Nous allons maintenant obtenir le contenu du serveur jusqu'à ce que l'intégralité du message que nous avons envoyé nous soit renvoyée en écho.
Pour obtenir des données, nous appelons la méthode recv de l'objet socket. Cette méthode reçoit en entrée un nombre avec la quantité maximale de données pouvant être reçues à la fois et renvoie une chaîne représentant les données reçues [1] (j'utilise Python 2.7, mais certaines versions de Python renvoient un objet byte plutôt qu'une chaîne ).
Puisque nous savons que le serveur renverra le message, nous voulons recevoir autant de données que nous en avons envoyées. Donc, nous allons déclarer une chaîne vide et continuer à demander des données et les ajouter à cette chaîne jusqu'à ce que sa taille soit égale à la taille de la chaîne que nous avons envoyée.
Nous spécifierons 1 pour l'argument d'entrée de la méthode recv , nous savons donc que chaque appel renverra une chaîne avec un seul caractère.
1 2 3 4 5 6 | data = "" while len (data)< len (message): data + = sock.recv( 1 ) print (data) |
Après avoir reçu et imprimé le message en écho, nous appelons la méthode close sur l'objet socket pour fermer la connexion. Le code 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 | import socket sock = socket.socket() host = "192.168.1.78" #ESP32 IP in local network port = 80 #ESP32 Server Port sock.connect((host, port)) message = "Hello World" sock.send(message) data = "" while len (data) < len (message): data + = sock.recv( 1 ) print (data) sock.close() |
Le code Arduino
Nous commençons notre code en important la bibliothèque WiFi.h , afin de pouvoir connecter l'ESP32 à un réseau WiFi.
1 | #include <WiFi.h> |
Ensuite, nous allons déclarer deux variables globales pour stocker les informations d'identification du réseau WiFi, plus précisément le nom du réseau (ssid) et le mot de passe. Vous devez placer ici les informations d'identification du réseau WiFi auquel vous allez vous connecter.
1 2 | const char * ssid = "YourNetworkName" ; const char * password = "YourNetworkPassword" ; |
Nous aurons également besoin d'une variable globale finale, qui sera un objet de la classe WiFiServer . Cette classe contient les méthodes dont nous aurons besoin pour définir un serveur de socket et accepter les connexions des clients.
Le constructeur de cette classe reçoit en entrée un entier avec le numéro de port où le serveur sera à l'écoute. Nous utiliserons le port 80 , qui correspond à la valeur utilisée sur le code client Python.
1 | WiFiServer wifiServer(80); |
Dans notre fonction de configuration, nous commencerons par ouvrir une connexion série, pour ensuite sortir des messages d'information de notre programme.
Ensuite, nous nous connecterons au réseau WiFi. Si vous avez besoin d'une explication détaillée sur la façon de le faire, veuillez consulter ce post précédent.
Pour finaliser la fonction setup, nous allons appeler la méthode begin sur notre objet WiFiServer , qui va initialiser notre serveur socket. Vous pouvez vérifier la fonction de configuration complète ci-dessous.
1 2 3 4 5 6 7 8 9 dix 11 12 13 14 15 16 17 18 | void setup() { Serial.begin(115200); delay(1000); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println( "Connecting to WiFi.." ); } Serial.println( "Connected to the WiFi network" ); Serial.println(WiFi.localIP()); wifiServer.begin(); } |
Maintenant que nous avons terminé la fonction de configuration, nous allons gérer les connexions client réelles et l'échange de données sur la boucle principale Arduino.
Pour commencer, nous allons vérifier si un client s'est connecté en appelant la méthode disponible sur notre objet global WiFiServer . Cette méthode ne prend aucun argument et renvoie un objet de classe WiFiClient .
1 | WiFiClient client = wifiServer.available(); |
Ensuite, nous devons vérifier si un client est bien connecté. Nous pouvons le faire à la fois en appelant la méthode connectée de l'objet WiFiClient ou en vérifiant cet objet avec une condition IF . Notez que la méthode connected renvoie true si un client est connecté et false sinon.
En ce qui concerne la deuxième option consistant à enfermer l' objet WiFiClient dans une condition IF , cela est possible car dans l' implémentation de la classe, l'opérateur bool C++ est surchargé et il appelle en fait la méthode connectée et renvoie sa valeur.
Notez que la surcharge d'opérateur est une fonctionnalité avancée du langage C++ (qui est le langage sur lequel Arduino est construit) dont nous n'avons pas à nous soucier et je le mentionne simplement à titre d'information.
1 2 3 | if (client) { // Data exchange with the client } |
Si la condition précédente est vraie, nous allons alors démarrer une boucle pendant que le client est connecté. Dans ce cas, nous appellerons explicitement la méthode connectée de l'objet WiFiClient .
Lorsque la boucle précédente se casse, cela signifie que le client n'est plus connecté. Ainsi, nous appelons la méthode stop sur notre WiFiClient pour libérer toutes les ressources puis imprimons un message indiquant le client déconnecté.
1 2 3 4 5 6 7 8 | if (client) { while (client.connected()) { // Data exchange with the client } client.stop(); Serial.println( "Client disconnected" ); } |
Dans la boucle while mentionnée précédemment, nous pouvons vérifier si le client a envoyé des données avec la méthode disponible . Cette méthode renvoie le nombre d'octets disponibles pour la lecture.
Ainsi, tant que le nombre d'octets est supérieur à zéro, nous continuerons à lire octet par octet avec un appel à la méthode read de l'objet WiFiClient , qui renverra un octet à chaque appel.
Ensuite, nous renverrons simplement chaque octet au client avec l'appel à la méthode d' écriture , en passant en entrée l'octet à envoyer.
Le code source final peut être vu ci-dessous et inclut déjà ces appels de fonction.
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 46 47 | #include <WiFi.h> const char * ssid = "YourNetworkName" ; const char * password = "YourNetworkPassword" ; WiFiServer wifiServer(80); void setup() { Serial.begin(115200); delay(1000); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println( "Connecting to WiFi.." ); } Serial.println( "Connected to the WiFi network" ); Serial.println(WiFi.localIP()); wifiServer.begin(); } void loop() { WiFiClient client = wifiServer.available(); if (client) { while (client.connected()) { while (client.available()>0) { char c = client.read(); client.write(c); } delay(10); } client.stop(); Serial.println( "Client disconnected" ); } } |
Tester le code
Pour tester l'ensemble du système, téléchargez simplement le code sur votre ESP32 à l'aide de l'IDE Arduino. Ouvrez ensuite le moniteur série IDE et copiez l'adresse IP qui est imprimée lors d'une connexion réussie de l'ESP32 au réseau WiFi. C'est l'adresse IP qui doit être utilisée sur le code Arduino.
Ensuite, avec l'ESP32 exécutant déjà le code du serveur, exécutez le code Python. Vous devriez obtenir une sortie similaire à la figure 1, qui montre que les données envoyées au serveur sont renvoyées en écho, comme prévu.
Figure 1 – Sortie du programme client Python.
Si vous revenez au moniteur série, un message indiquant que le client est déconnecté doit être imprimé, comme illustré à la figure 2. Cela indique que le serveur a correctement détecté que le client n'est plus connecté, ce qui est le comportement attendu après le code Python appelle la méthode close pour mettre fin à la connexion.
Figure 2 – Sortie du programme ESP32, après la déconnexion du client.
Commentaires
Enregistrer un commentaire