Programme avancé: Contrôle d’une LED par Wifi
import socket
import network
import machine
import time
# Identifiants Wifi
ssid = 'LiveBox_1324'
mot_de_passe = '12345?ABCDE'
# Configuration de la LED
led = machine.Pin(4, machine.Pin.OUT)
led.off()
clignotement_led = False
# Configuration du timer
timer = machine.Timer(0)
# Connexion WiFi
print("Démarrage du module…")
client_wifi = network.WLAN(network.STA_IF)
client_wifi.active(True)
if not client_wifi.isconnected():
print("Connexion au réseau…")
client_wifi.connect(ssid, mot_de_passe)
# Tentative pendant 10 secondes
delai_attente = 10
while not client_wifi.isconnected() and delai_attente > 0:
time.sleep(1)
delai_attente -= 1
print("En attente…")
if client_wifi.isconnected():
print("Connecté !")
print("Configuration réseau :", client_wifi.ifconfig())
else:
print("Échec de connexion WiFi")
# Donne le libellé de l'état de la led
def donner_etat_led():
if clignotement_led:
return "Clignotante"
return "Allumée" if led.value() else "Éteinte"
# Appelée par timer
def callback_clignotement(t):
led.value(not led.value())
# Page Web HTML
def page_web():
state = donner_etat_led()
html = f"""
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Serveur Web ESP32</title>
<style>
body {{
background: #121212;
color: #fff;
font-family: Arial, sans-serif;
text-align: center;
padding: 40px;
}}
.btn {{
padding: 12px 25px;
margin: 10px;
border: none;
border-radius: 8px;
font-size: 18px;
cursor: pointer;
color: white;
}}
.on {{ background:#4CAF50; }}
.off {{ background:#F44336; }}
.blink {{ background:#FF9800; }}
</style>
</head>
<body>
<h2>Serveur Web ESP32</h2>
<p>Contrôlez la LED du module via cette interface.</p>
<form>
<button class="btn on" name="LED" value="1">Allumer</button>
<button class="btn off" name="LED" value="0">Éteindre</button>
<button class="btn blink" name="LED" value="2">Clignoter</button>
</form>
<p>État actuel : <strong>{state}</strong></p>
</body>
</html>
"""
return html
# Configuration du socket du serveur Web
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind(('', 80))
socket.listen(10)
print("Serveur Web démarré sur port 80…")
# Boucle principale
while True:
connexion, adresse_ip = socket.accept()
print("Connexion reçue depuis :", adresse_ip)
requete = connexion.recv(1024).decode()
print("Requête HTTP :", requete)
# Analyse requête
if "/?LED=1" in requete:
print("Commande : LED allumée")
led.value(1)
if clignotement_led:
timer.deinit()
clignotement_led = False
elif "/?LED=0" in requete:
print("Commande : LED éteinte")
led.value(0)
if clignotement_led:
timer.deinit()
clignotement_led = False
elif "/?LED=2" in requete:
print("Commande : LED clignotante")
if not clignotement_led:
clignotement_led = True
timer.init(period=500, mode=machine.Timer.PERIODIC, callback=callback_clignotement)
# Envoi réponse
response = page_web()
connexion.send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n")
connexion.sendall(response)
connexion.close()
Le code expliqué
1) Imports initiaux
import socket import network import machine import time
- socket : Permet de créer un serveur web en gérant les connexions réseau TCP/IP
- network : Gère la connexion WiFi de l’ESP32
- machine : Donne accès au matériel (GPIO, timers, etc.)
- time : Gère les temporisations et délais
2) Déclaration des identifiants Wifi
ssid = 'LiveBox_1324' mot_de_passe = '12345?ABCDE'
Cette section centralise les informations de connexion.
Important : Remplacez ‘LiveBox_1324’ par le nom de votre réseau Wifi (SSID) et ‘12345?ABCDE’ par votre véritable mot de passe.
3) Configuration de la LED
led = machine.Pin(4, machine.Pin.OUT) led.off() clignotement_led = False
On initialise la broche GPIO 4 en mode sortie (Pin.OUT), ce qui permettra de piloter la LED. La méthode led.off() garantit que la LED est éteinte au démarrage. La variable booléenne clignotement_led indique si le mode clignotement est actif..
4) Connexion WiFi
client_wifi = network.WLAN(network.STA_IF) client_wifi.active(True)
network.STA_IF signifie « Station Interface », c’est-à-dire que l’ESP32 se comporte comme un client WiFi (comme votre smartphone ou ordinateur) qui se connecte à un routeur existant. L’alternative serait network.AP_IF (Access Point Interface) où l’ESP32 créerait son propre réseau Wifi.
La méthode active(True) active la puce WiFi de l’ESP32.
if not client_wifi.isconnected():
print("Connexion au réseau…")
client_wifi.connect(ssid, mot_de_passe)
# Tentative pendant 10 secondes
delai_attente = 10
while not client_wifi.isconnected() and delai_attente > 0:
time.sleep(1)
delai_attente -= 1
print("En attente…")
Cette boucle attend jusqu’à 10 secondes que la connexion Wifi s’établisse. À chaque seconde, elle vérifie si la connexion est établie (isconnected()). Si, au bout de 10 secondes, la connexion échoue, le programme continue malgré tout (mais le serveur web ne fonctionnera pas).
if client_wifi.isconnected():
print("Connecté !")
print("Configuration réseau :", client_wifi.ifconfig())
else:
print("Échec de connexion WiFi")
La méthode ifconfig() renvoie un tableau (tuple) de 4 éléments :
- Adresse IP de l’ESP32 (ex: 192.168.1.42)
- Masque de sous-réseau (ex: 255.255.255.0)
- Passerelle (adresse du routeur)
- Serveur DNS
L’adresse IP va permettre d’accéder au serveur web.
5) Déterminer l’état de la LED
def donner_etat_led():
if clignotement_led:
return "Clignotante"
return "Allumée" if led.value() else "Éteinte"
Cette fonction retourne une chaîne de caractères décrivant l’état actuel de la LED :
- Si le mode clignotement est actif, on retourne toujours « Clignotante » (peu importe l’état instantané).
- Sinon, led.value() retourne 1 (True) si la LED est allumée, 0 (False) si elle est éteinte.
6) Timer matériel et callback
timer = machine.Timer(0)
Le Timer est un composant matériel de l’ESP32 qui exécute du code à intervalles réguliers sans bloquer le programme principal. C’est beaucoup plus fiable qu’une boucle while avec des sleep().
L’instruction machine.Timer(0) précise que l’on utilise le timer matériel numéro 0 (l’ESP32 en possède 4).
def callback_clignotement(t):
led.value(not led.value())
Le timer appel régulièrement callback_clignotement(t). Le paramètre t (timer) de cette fonction est automatiquement passé par le système, mais nous ne l’utilisons pas ici.
La ligne led.value(not led.value()) est une astuce élégante qui permet d’inverser l’état lu de la LED. Résultat : la LED change d’état à chaque appel, créant le clignotement.
7) Page HTML
def page_web():
state = donner_etat_led()
html = f"""
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Serveur Web ESP32</title>
<style>
body {{
background: #121212;
color: #fff;
font-family: Arial, sans-serif;
text-align: center;
padding: 40px;
}}
.btn {{
padding: 12px 25px;
margin: 10px;
border: none;
border-radius: 8px;
font-size: 18px;
cursor: pointer;
color: white;
}}
.on {{ background:#4CAF50; }}
.off {{ background:#F44336; }}
.blink {{ background:#FF9800; }}
</style>
</head>
<body>
<h2>Serveur Web ESP32</h2>
<p>Contrôlez la LED du module via cette interface.</p>
<form>
<button class="btn on" name="LED" value="1">Allumer</button>
<button class="btn off" name="LED" value="0">Éteindre</button>
<button class="btn blink" name="LED" value="2">Clignoter</button>
</form>
<p>État actuel : <strong>{state}</strong></p>
</body>
</html>
"""
return html
Points à comprendre :
- f-string (f »… ») : Permet d’insérer des variables Python dans une chaîne avec {variable}. Ici, {state} sera remplacé par « Allumée », « Éteinte » ou « Clignotante ».
- Doubles accolades {{ et }} : Dans une f-string, les accolades simples {} servent à insérer des variables Python. Pour avoir des accolades littérales dans le CSS (pour définir les styles), il faut les doubler : {{ devient { dans le HTML final.
- Les boutons HTML : Chaque <button> possède deux attributs cruciaux :
– name= »LED » : Le nom du paramètre envoyé au serveur
– value= »1″ (ou 0, ou 2) : La valeur associée
Quand vous cliquez sur un bouton, le navigateur envoie une requête du type : http://192.168.1.42/?LED=1 - Balise <form> : Nous ne renseignons pas d’attribut action afin que le formulaire envoie la requête vers la même URL (l’adresse de l’ESP32).
8) Configuration du socket serveur
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind(('', 80))
socket.listen(10)
Explication de chaque ligne:
- socket.socket(socket.AF_INET, socket.SOCK_STREAM) :
AF_INET : Signifie « Address Family Internet », donc on utilise le protocole IPv4 (adresses du type 192.168.x.x)
SOCK_STREAM : Indique qu’on utilise le protocole TCP plutôt que UDP - socket.bind(( », 80)) : On réserve le port 80 pour notre serveur
- socket.listen(10) : Le serveur peut mettre en file d’attente jusqu’à 10 connexions simultanées. Si 11 clients tentent de se connecter en même temps, le 11ème devra attendre
9) Boucle principale et traitement des requêtes
while True:
connexion, adresse_ip = socket.accept()
print("Connexion reçue depuis :", adresse_ip)
socket.accept() est une méthode bloquante : le programme s’arrête ici et attend qu’un client se connecte. Quand quelqu’un accède à l’URL dans son navigateur, cette ligne se « débloque » et retourne :
- connexion : Un nouvel objet socket pour communiquer avec ce client spécifique.
- adresse_ip : Un tuple contenant l’adresse IP et le port du client (ex: (‘192.168.1.50’, 54321))
requete = connexion.recv(1024).decode()
print("Requête HTTP :", requete)
.decode() : Convertit les bytes (données brutes) en string (chaîne de caractères) en utilisant l’encodage UTF-8.
if "/?LED=1" in requete:
print("Commande : LED allumée")
led.value(1)
if clignotement_led:
timer.deinit()
clignotement_led = False
On cherche simplement si la chaîne « /?LED=1 » apparaît quelque part dans la requête HTTP. Si oui :
- On allume la LED avec led.value(1).
- Si le mode clignotement était actif, on le désactive proprement :
timer.deinit() : Arrête le timer matériel (sinon il continuerait à inverser l’état de la LED !)
clignotement_led = False : Met à jour notre drapeau
elif "/?LED=2" in requete:
print("Commande : LED clignotante")
if not clignotement_led:
clignotement_led = True
timer.init(period=500, mode=machine.Timer.PERIODIC, callback=callback_clignotement)
Pour le mode clignotement :
- On vérifie d’abord que le clignotement n’est pas déjà actif (pour éviter de démarrer plusieurs timers)
- timer.init(…) démarre le timer avec ces paramètres :
– period=500 : Intervalle de 500 millisecondes (0,5 seconde)
– mode=machine.Timer.PERIODIC : Le timer se répète indéfiniment (plutôt que de s’exécuter une seule fois)
– callback=callback_clignotement : La fonction à appeler à chaque intervalle
11) Envoi de la réponse HTTP
response = page_web()
connexion.send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n")
connexion.sendall(response)
connexion.close()
- En-tête HTTP : La première ligne envoyée doit respecter le protocole HTTP :
– HTTP/1.1 200 OK : Version du protocole + code de statut (200 = succès)
– Content-Type: text/html : Indique que le contenu est du HTML
– Connection: close : Indique qu’on ferme la connexion après l’envoi (pas de connexion persistante)
– \r\n : Retour chariot + saut de ligne (standard HTTP)
– \r\n\r\n : Une ligne vide obligatoire qui sépare l’en-tête du corps de la réponse - sendall(response) : Envoie tout le contenu HTML. La méthode sendall() garantit que toutes les données sont envoyées, même si le buffer réseau est plein (contrairement à send() qui peut n’envoyer qu’une partie).
- connexion.close() : Ferme proprement la connexion avec ce client. Sinon le navigateur resterait en attente !
Exécution du code
Nous utilisons le mode REPL pour la première exécution du code afin de vérifier que tout se déroule bien et pour noter l’adresse IP qui sera attribuée à l’ESP32.
Pensez à bien modifier les identifiants Wifi en haut début code (variables `ssid` et `mot_de_passe`).
A l’exécution du code vous voyez les message suivants s’afficher dans la console Thonny:
MPY: soft reboot
Démarrage du module…
Connexion au réseau…
En attente…
En attente…
En attente…
En attente…
En attente…
Connecté !
Configuration réseau : ('192.168.1.31', '255.255.255.0', '192.168.1.1', '192.168.1.1')
Serveur Web démarré sur port 80…
L’adresse IP de votre ESP32 est le premier nombre entre parenthèses (ici 192.168.1.31).
Ouvrez un navigateur web sur n‘importe quel appareil connecté au même réseau Wifi comme par exemple votre smartphone et entrez l’adresse IP de votre ESP32 : http://192.168.1.31.
Vous accédez alors à l’interface de contrôle avec trois boutons :

Et voici le résultat que vous obtenez:
