Guides · 18 min de lecture

ESP32 MQTT : tutoriel Mosquitto, Home Assistant et ESPHome

Tutoriel ESP32 MQTT : installer Mosquitto, publier des capteurs et piloter un relais avec PubSubClient, découverte Home Assistant, YAML ESPHome et QoS.

Le duo ESP32 et MQTT est la façon la plus répandue de faire dialoguer les capteurs et relais de ta maison entre eux et avec une box domotique comme Home Assistant. MQTT est un protocole de messagerie léger conçu pour les petits appareils : l'ESP32 dépose la température mesurée dans un topic comme "ev/salon/sicaklik", et chaque programme abonné à ce topic reçoit la valeur instantanément. De la même manière, quand tu appuies sur un bouton dans l'application Home Assistant de ton téléphone, la commande "ON" atteint l'ESP32 en bien moins d'une seconde et enclenche le relais. Contrairement à HTTP, il n'ouvre pas une nouvelle connexion à chaque requête ; il fonctionne sur une seule connexion ouverte avec des en-têtes de deux octets seulement, ce qui le rend rapide et économe pour le Wi-Fi comme pour le processeur.

Dans ce guide, tu vas construire de zéro un nœud domotique fonctionnel. Tu découvriras d'abord les notions MQTT de broker, topic, publish et subscribe, puis tu installeras le broker Mosquitto dans Home Assistant ou sur un Raspberry Pi. Ensuite, avec la bibliothèque PubSubClient, tu publieras depuis l'ESP32 la température et l'humidité d'un DHT22, tu écouteras les commandes d'un relais et tu ajouteras MQTT Discovery pour que l'appareil apparaisse tout seul dans Home Assistant. Nous verrons aussi QoS et retain, le message de dernière volonté (LWT) qui affiche l'appareil comme « indisponible » quand la connexion tombe, l'alternative ESPHome qui fait la même chose sans écrire de C++, les différences avec l'ESP8266 et le Raspberry Pi Pico W, ainsi que les erreurs les plus fréquentes une par une.

Carte de développement ESP32 connectée à Home Assistant via MQTT
Grâce à son Wi-Fi intégré, l'ESP32 se connecte directement au broker MQTT du réseau domestique ; les données des capteurs et les commandes du relais passent par la même connexion.

Qu'est-ce que MQTT et comment ça marche ?

MQTT (Message Queuing Telemetry Transport) repose sur un modèle publication/abonnement. Au centre se trouve un serveur appelé broker ; l'ESP32, Home Assistant, ton téléphone ou un programme sur ton ordinateur s'y connectent en tant que clients. Les clients ne se connaissent pas et ignorent les adresses IP des autres : l'un publie un message dans un topic, et le broker le transmet à tous ceux qui sont abonnés à ce topic. Vois-le comme un bureau de poste : l'ESP32 dépose une lettre dans la boîte "ev/salon/sicaklik", et Home Assistant, qui surveille cette boîte, la reçoit aussitôt. Comme c'est toujours le client qui ouvre la connexion, l'ESP32 n'a besoin ni d'une IP fixe ni d'un port ouvert sur la box ; il lui suffit de connaître l'adresse du broker.

NotionÀ quoi ça sert ?Exemple
BrokerServeur qui reçoit les messages et les distribue aux abonnésMosquitto, le broker Mosquitto de Home Assistant
ClientTout appareil ou programme connecté au broker ; chacun a un identifiant unique (client ID)ESP32, Home Assistant, MQTT Explorer
Topic (sujet)Adresse du message, faite de niveaux séparés par des barres obliquesev/salon/sicaklik
Publish (publier)Envoyer un message dans un topicEnvoyer la valeur "23.4" dans ev/salon/sicaklik
Subscribe (s'abonner)S'inscrire pour recevoir les messages d'un topicL'ESP32 qui écoute ev/salon/role/komut
Payload (charge utile)Contenu du message : texte, nombre ou JSONON, 23.4, {"sicaklik":23.4}
RetainLe broker garde le dernier message d'un topic et le remet tout de suite aux nouveaux abonnésÉtat du relais : ON
LWT (dernière volonté)Message que le broker publie au nom d'un client qui disparaît sans prévenirev/salon/baglanti : offline
QoSNiveau de garantie de livraison du message (0, 1 ou 2)QoS 1 pour les commandes du relais

Pourquoi MQTT ? Comparaison avec un serveur web, Blynk et Telegram

MéthodeAvantagesInconvénientsIdéal pour
MQTT + Home AssistantLocal et rapide, bidirectionnel ; des centaines d'appareils sur un tableau de bord, automatisationsIl faut faire tourner un brokerGérer toute la maison depuis un seul endroit
Serveur web sur l'ESP32Pas de serveur en plus, s'ouvre dans le navigateurChaque appareil a sa propre page, pas d'automatisations entre appareilsPanneau de contrôle d'un seul appareil
Blynk IoTTableau de bord mobile tout prêt, accès par internetDépend du cloud, limites dans l'offre gratuitePrototypes mobiles rapides
Bot TelegramNotifications instantanées gratuites, pas de port à ouvrirNi graphiques ni tableau de bordAlarmes et commandes simples
ESP-NOWLes cartes ESP communiquent sans box ni brokerUniquement entre cartes ESP, n'atteint pas Home Assistant directementAcheminer les données d'un capteur sur pile vers une passerelle

En bref, MQTT prend tout son intérêt quand le nombre d'appareils grandit : quand tu ajoutes un capteur, tu ne touches à aucun code existant, tu commences simplement à publier dans un nouveau topic. Pour piloter un seul appareil depuis le navigateur, le guide ESP32 Async Web Server et WebSocket va plus vite ; pour des notifications sur le téléphone, vois Bot Telegram avec l'ESP32, et pour un tableau de bord mobile tout prêt, Blynk avec l'ESP32. Pour un capteur au fond du jardin, hors de portée de la box, une bonne solution consiste à envoyer les données par ESP-NOW vers un ESP32 passerelle connecté à MQTT.

Structure des topics MQTT et caractères génériques

Les topics ressemblent à des chemins de dossiers : "ev/salon/sicaklik" (en turc, maison/salon/température) compte trois niveaux et respecte la casse, donc "Ev/Salon" et "ev/salon" sont deux topics différents. Ne commence pas par une barre oblique ("/ev/salon" crée un premier niveau vide) et évite les espaces et les accents ; des lettres simples, des chiffres, des tirets et des tirets bas suffisent. À l'abonnement, tu peux utiliser deux caractères génériques : + remplace exactement un niveau ("ev/+/sicaklik" renvoie la température de toutes les pièces), tandis que # couvre tout ce qui suit et ne peut figurer qu'à la fin ("ev/#" renvoie tous les messages de la maison). Ces jokers ne valent que pour l'abonnement ; un message est toujours publié dans un topic précis. Les topics qui commencent par $ (comme $SYS) sont réservés aux statistiques du broker et ne sont pas couverts par un abonnement à #. Pour le projet de ce guide, nous utiliserons cette organisation :

TopicPublié parÉcouté parRetain
ev/salon/sicaklikESP32 (toutes les 30 secondes)Home AssistantOui
ev/salon/nemESP32 (toutes les 30 secondes)Home AssistantOui
ev/salon/role/komutHome Assistant, téléphone, automatisationsESP32Non
ev/salon/role/durumESP32 (à chaque changement)Home AssistantOui
ev/salon/baglantiESP32 (online), broker (offline)Home AssistantOui
homeassistant/statusHome Assistant (online au démarrage)ESP32Non

Installer un broker MQTT : Mosquitto

Le broker MQTT gratuit le plus répandu est Eclipse Mosquitto ; même sur un Raspberry Pi, il traite sans peine des centaines de messages par seconde. Il existe trois façons simples de l'installer : l'application officielle Mosquitto broker si tu utilises Home Assistant OS, le paquet apt sur un Raspberry Pi ou un ordinateur Linux séparé, ou l'installateur Mosquitto sous Windows. Quel que soit ton choix, le broker utilise le port 1883 pour le MQTT non chiffré et le port 8883 pour le MQTT chiffré en TLS, et il doit simplement se trouver sur le même réseau domestique que l'ESP32. Dans Home Assistant, l'installation se déroule ainsi :

  1. Dans Home Assistant, ouvre Paramètres > Applications (cette section s'appelle Modules complémentaires ou Add-ons dans les anciennes versions), clique sur Installer une application et choisis Mosquitto broker dans la liste.
  2. Clique sur Installer ; une fois terminé, clique sur Démarrer et laisse activée l'option de démarrage automatique.
  3. Crée un utilisateur dédié à l'ESP32 : dans Paramètres > Personnes > Utilisateurs, ajoute un utilisateur "esp32" avec un mot de passe solide. Si tu ne vois pas cet onglet, active le mode avancé dans ton profil. Les noms "homeassistant" et "addons" sont réservés au broker, ne les utilise pas.
  4. Sur la page Paramètres > Appareils et services, l'intégration MQTT apparaît généralement toute seule comme « Découvert » ; clique sur Configurer et valide. Sinon, cherche MQTT via Ajouter une intégration et choisis l'option qui configure Mosquitto automatiquement.
  5. Dans le code de l'ESP32, tu indiqueras l'adresse IP de Home Assistant comme adresse du broker (par exemple 192.168.1.10), 1883 comme port et l'utilisateur que tu viens de créer.

Sur une machine Linux comme un Raspberry Pi ou Ubuntu, quelques commandes suffisent. Installe le broker et les outils de test avec sudo apt install mosquitto mosquitto-clients. Crée l'utilisateur "esp32" avec sudo mosquitto_passwd -c /etc/mosquitto/passwd esp32 et saisis le mot de passe deux fois ; l'option -c crée le fichier de zéro, alors ne la mets pas quand tu ajoutes un deuxième utilisateur, sinon les précédents seront effacés. Crée ensuite un fichier local.conf dans le dossier /etc/mosquitto/conf.d/, écris-y les trois lignes ci-dessous et redémarre le service avec sudo systemctl restart mosquitto. Sous Windows, ajoute les mêmes lignes au fichier mosquitto.conf du dossier d'installation et redémarre le service Mosquitto Broker.

LigneSignification
listener 1883Écoute le port 1883 sur toutes les interfaces réseau ; sans cette ligne, Mosquitto 2.x n'accepte que les connexions venant du même ordinateur
allow_anonymous falseRefuse les connexions sans nom d'utilisateur ni mot de passe ; c'est déjà le défaut en 2.x, mais l'écrire est une bonne habitude
password_file /etc/mosquitto/passwdUtilise le fichier de mots de passe créé avec mosquitto_passwd ; les mots de passe y sont stockés sous forme de hachage
Si aucun listener n'est défini dans la configuration, Mosquitto 2.0 et les versions suivantes n'écoutent que sur 127.0.0.1 et écrivent dans le journal l'avertissement "Starting in local only mode. Connections will only be possible from clients running on this machine.". Dans ce cas, l'ESP32 ne peut pas se connecter et tu obtiens l'erreur rc=-2. À l'inverse, n'ouvre jamais le port 1883 vers internet sur ta box (pas de redirection de port) : le trafic MQTT non chiffré peut être lu en chemin et les relais de ta maison pourraient tomber entre de mauvaises mains. Si tu as besoin d'un accès depuis l'extérieur, utilise un VPN ou les solutions d'accès à distance de Home Assistant.

Avant de passer à l'ESP32, teste le broker depuis ton ordinateur ; séparer d'emblée les problèmes de broker et de code te fait gagner beaucoup de temps. Dans un terminal, écoute tous les topics de la maison avec mosquitto_sub -h 192.168.1.10 -u esp32 -P tonmotdepasse -t "ev/#" -v. Dans un second terminal, tape mosquitto_pub -h 192.168.1.10 -u esp32 -P tonmotdepasse -t ev/salon/test -m bonjour. Si la ligne "ev/salon/test bonjour" apparaît dans le premier terminal, le broker fonctionne et le mot de passe est bon. L'option -v affiche le topic devant chaque message, et l'option -r envoie le message en mode retain.

Si tu n'aimes pas la ligne de commande, le logiciel gratuit MQTT Explorer affiche tous les topics du broker sous forme d'arbre, avec les dernières valeurs et les indicateurs retain. Dans Home Assistant, tu peux aussi aller dans Paramètres > Appareils et services > MQTT > Configurer, taper ev/# dans le champ « Écouter un sujet » et lancer l'écoute, puis utiliser la partie « Publier un paquet » pour envoyer des commandes à l'ESP32 à la main.

Matériel nécessaire et schéma de câblage

Pour ce projet, il te faut une carte de développement ESP32, un capteur de température et d'humidité DHT22, un module relais pilotable en 3,3 V, une breadboard et des fils de liaison. Le DHT22 est plus précis que le DHT11 : il mesure la température à ±0,5 °C et l'humidité à environ ±2–5 %, et fonctionne de -40 à 80 °C ; nous présentons cette famille de capteurs en détail dans Capteur de température et d'humidité DHT11. Si tu as un DHT11, remplace simplement DHT22 par DHT11 dans le code. Pour le premier test de connexion, un ESP32 et un câble USB suffisent ; tu pourras ajouter le capteur et le relais ensuite.

ESP32
ESP32
DHT22
DHT22
Module relais
Module relais
ConnexionESP32ESP8266 (NodeMCU)Raspberry Pi Pico W
DHT22 VCC3V33V33V3(OUT)
DHT22 DATAGPIO 4D2 (GPIO 4)GP15
DHT22 GNDGNDGNDGND
Relais VCCVIN (5V)VIN (5V)VBUS (5V)
Relais INGPIO 26D1 (GPIO 5)GP14
Relais GNDGNDGNDGND
Les broches de l'ESP32, de l'ESP8266 et de la Pico fonctionnent en 3,3 V et ne tolèrent pas le 5 V ; c'est pourquoi nous alimentons le DHT22 par la broche 3V3. Les modules DHT22 à trois broches ont généralement déjà une résistance de rappel (pull-up) sur la carte ; si tu utilises le capteur nu à quatre pattes, ajoute une résistance de 4,7–10 kΩ entre DATA et VCC. Si tu commutes une charge secteur en 230 V avec le relais, fais tout le câblage prise débranchée et demande l'aide d'un adulte ; les détails sont dans Qu'est-ce qu'un module relais ?. Tu peux voir toutes les broches de ta carte dans l'outil Pinout.

Installer PubSubClient dans l'IDE Arduino

  1. Si le paquet de cartes ESP32 n'est pas encore installé dans l'IDE Arduino, installe-le d'abord ; les étapes sont dans Qu'est-ce que l'ESP32 ?.
  2. Ouvre Outils > Gérer les bibliothèques, tape PubSubClient dans le champ de recherche et installe la bibliothèque de Nick O'Leary. Le code de ce guide a été compilé avec la version 2.8.
  3. Dans la même fenêtre, cherche DHT sensor library et installe la bibliothèque d'Adafruit ; quand elle demande les dépendances, choisis Install all pour installer aussi Adafruit Unified Sensor.
  4. Si tu rencontres des problèmes pour installer les bibliothèques, consulte le guide Ajouter une bibliothèque Arduino.

Premier test : connecter l'ESP32 au broker MQTT

Avant d'ajouter les capteurs, vérifions avec le code le plus simple possible que les identifiants Wi-Fi, l'adresse du broker et le mot de passe sont corrects. Le code ci-dessous se connecte au broker, publie "merhaba" (bonjour) dans le topic "test/esp32/durum" et affiche dans le moniteur série chaque message reçu sur "test/esp32/komut". Remplace le nom du Wi-Fi, le mot de passe, l'IP du broker et l'utilisateur MQTT par les tiens, téléverse le code et ouvre le moniteur série à 115200 bauds :

C++ (Arduino IDE)
1#include <WiFi.h>
2#include <PubSubClient.h>
3
4const char* WIFI_SSID = "AgAdi";              // Wi-Fi adın (yalnız 2,4 GHz) / your Wi-Fi name (2.4 GHz only)
5const char* WIFI_PASS = "Sifre123";           // Wi-Fi şifren / your Wi-Fi password
6const char* MQTT_SUNUCU = "192.168.1.10";     // broker'ın IP adresi / broker IP address
7const int   MQTT_PORT = 1883;                 // şifresiz MQTT portu / unencrypted MQTT port
8const char* MQTT_KULLANICI = "esp32";         // broker kullanıcı adı / broker username
9const char* MQTT_SIFRE = "mqttSifre";         // broker şifresi / broker password
10
11WiFiClient wifiIstemci;                       // TCP bağlantısı / TCP connection
12PubSubClient mqtt(wifiIstemci);               // MQTT istemcisi / MQTT client
13
14// Abone olunan konuya mesaj gelince çalışır / runs when a subscribed topic receives a message
15void mesajGeldi(char* topic, byte* payload, unsigned int length) {
16  Serial.print("Mesaj [");
17  Serial.print(topic);
18  Serial.print("] ");
19  for (unsigned int i = 0; i < length; i++) {
20    Serial.print((char)payload[i]);           // payload sonunda \0 yoktur / payload is not null-terminated
21  }
22  Serial.println();
23}
24
25void setup() {
26  Serial.begin(115200);
27  WiFi.mode(WIFI_STA);
28  WiFi.begin(WIFI_SSID, WIFI_PASS);
29  while (WiFi.status() != WL_CONNECTED) {
30    delay(500);
31    Serial.print(".");
32  }
33  Serial.print("\nIP: ");
34  Serial.println(WiFi.localIP());
35
36  mqtt.setServer(MQTT_SUNUCU, MQTT_PORT);     // broker adresi / broker address
37  mqtt.setCallback(mesajGeldi);               // gelen mesaj fonksiyonu / incoming message handler
38}
39
40void loop() {
41  if (!mqtt.connected()) {
42    Serial.print("MQTT baglaniyor... ");
43    if (mqtt.connect("esp32-test", MQTT_KULLANICI, MQTT_SIFRE)) {   // istemci kimliği benzersiz olmalı / client ID must be unique
44      Serial.println("baglandi");
45      mqtt.subscribe("test/esp32/komut");                  // bu konuyu dinle / listen to this topic
46      mqtt.publish("test/esp32/durum", "merhaba");         // ilk mesaj / first message
47    } else {
48      Serial.print("hata, rc=");
49      Serial.println(mqtt.state());                        // hata kodu / error code
50      delay(5000);
51      return;
52    }
53  }
54  mqtt.loop();                                             // mesajları işle, bağlantıyı canlı tut / process messages, keep the connection alive
55}

Dès que tu vois "baglandi" (connecté) dans le moniteur série, envoie depuis un terminal de ton ordinateur mosquitto_pub -h 192.168.1.10 -u esp32 -P tonmotdepasse -t test/esp32/komut -m salut ; en quelques millisecondes, la ligne "Mesaj [test/esp32/komut] salut" apparaît dans le moniteur série. Si la connexion échoue, le code affiche un code d'erreur avec mqtt.state() et réessaie au bout de 5 secondes. Ces codes t'indiquent précisément où se trouve le problème :

rcNom dans PubSubClientSignification et solution
-4MQTT_CONNECTION_TIMEOUTLe broker n'a pas répondu à temps ; réseau faible ou broker surchargé
-3MQTT_CONNECTION_LOSTUne connexion établie a été perdue ; le plus souvent parce que loop() n'a pas été appelée pendant longtemps ou que le Wi-Fi a disparu
-2MQTT_CONNECT_FAILEDLa connexion TCP ne s'est jamais ouverte : IP ou port erronés, broker arrêté, Mosquitto en mode local uniquement ou pare-feu qui bloque le 1883
-1MQTT_DISCONNECTEDLa connexion a été fermée proprement (appel à disconnect) ou n'a jamais été établie
2MQTT_CONNECT_BAD_CLIENT_IDL'identifiant client a été refusé ; un client ID vide ou invalide a été utilisé
4MQTT_CONNECT_BAD_CREDENTIALSNom d'utilisateur ou mot de passe incorrect (certains brokers renvoient ce code)
5MQTT_CONNECT_UNAUTHORIZEDNon autorisé ; Mosquitto renvoie ce code aussi bien pour un mauvais mot de passe que pour une tentative de connexion sans identifiants

Publier des données de capteur et écouter les commandes du relais avec l'ESP32

Passons maintenant au vrai projet. Le code ci-dessous lit le DHT22 toutes les 30 secondes et publie la température et l'humidité avec le drapeau retain, pilote le relais avec les commandes ON, OFF et TOGGLE reçues sur "ev/salon/role/komut" et publie le nouvel état du relais dans "ev/salon/role/durum". À la connexion, il laisse une dernière volonté au broker, se présente à Home Assistant grâce à MQTT Discovery et, si la connexion tombe, il réessaie toutes les 5 secondes sans bloquer loop(). Grâce au bloc #if defined(ESP8266) en tête, le même code compile aussi tel quel pour un NodeMCU.

C++ (Arduino IDE)
1#if defined(ESP8266)
2#include <ESP8266WiFi.h>
3#else
4#include <WiFi.h>
5#endif
6#include <PubSubClient.h>
7#include <DHT.h>
8
9// ---- Ayarlar / Settings ----
10const char* WIFI_SSID = "AgAdi";
11const char* WIFI_PASS = "Sifre123";
12const char* MQTT_SUNUCU = "192.168.1.10";        // broker IP (Home Assistant ya da Raspberry Pi) / broker IP (Home Assistant or Raspberry Pi)
13const int   MQTT_PORT = 1883;
14const char* MQTT_KULLANICI = "esp32";
15const char* MQTT_SIFRE = "mqttSifre";
16const char* ISTEMCI_ID = "esp32-salon";          // her cihazda farklı olmalı / must be different on every device
17
18#if defined(ESP8266)
19const int DHT_PIN = 4;                           // NodeMCU D2
20const int ROLE_PIN = 5;                          // NodeMCU D1
21#else
22const int DHT_PIN = 4;                           // ESP32 GPIO 4
23const int ROLE_PIN = 26;                         // ESP32 GPIO 26
24#endif
25const bool ROLE_AKTIF_LOW = true;                // çoğu röle modülü LOW ile çeker / most relay modules switch on LOW
26const unsigned long OLCUM_ARALIGI = 30000;       // 30 saniyede bir ölçüm / one reading every 30 s
27
28// ---- Konular (topic) / Topics ----
29const char* T_SICAKLIK = "ev/salon/sicaklik";
30const char* T_NEM      = "ev/salon/nem";
31const char* T_KOMUT    = "ev/salon/role/komut";  // ON, OFF ya da TOGGLE / ON, OFF or TOGGLE
32const char* T_DURUM    = "ev/salon/role/durum";
33const char* T_BAGLANTI = "ev/salon/baglanti";    // online / offline (son vasiyet / last will)
34const char* T_HA_DURUM = "homeassistant/status"; // HA açılınca "online" yayınlar / HA publishes "online" when it starts
35
36WiFiClient wifiIstemci;
37PubSubClient mqtt(wifiIstemci);
38DHT dht(DHT_PIN, DHT22);
39
40bool roleAcik = false;
41unsigned long sonOlcum = 0;
42unsigned long sonDeneme = 0;
43
44// Röleyi sür ve yeni durumu kalıcı (retain) yayınla / drive the relay and publish the new state as retained
45void roleAyarla(bool acik) {
46  roleAcik = acik;
47  bool seviye = ROLE_AKTIF_LOW ? !acik : acik;
48  digitalWrite(ROLE_PIN, seviye ? HIGH : LOW);
49  mqtt.publish(T_DURUM, acik ? "ON" : "OFF", true);
50  Serial.println(acik ? "Role: ON" : "Role: OFF");
51}
52
53// Tek bir Home Assistant keşif mesajı gönder / send one Home Assistant discovery message
54void kesifYayinla(const char* tur, const char* nesne, const char* ad, const char* ekAlanlar) {
55  char konu[96];
56  snprintf(konu, sizeof(konu), "homeassistant/%s/%s/%s/config", tur, ISTEMCI_ID, nesne);
57  char json[600];
58  snprintf(json, sizeof(json),
59           "{\"name\":\"%s\",\"unique_id\":\"%s_%s\",%s,\"availability_topic\":\"%s\","
60           "\"device\":{\"identifiers\":[\"%s\"],\"name\":\"Salon ESP32\",\"model\":\"ESP32 + DHT22\"}}",
61           ad, ISTEMCI_ID, nesne, ekAlanlar, T_BAGLANTI, ISTEMCI_ID);
62  if (!mqtt.publish(konu, json, true)) {         // false: tampon küçük ya da bağlantı yok / false: buffer too small or not connected
63    Serial.println("Kesif mesaji gonderilemedi");
64  }
65}
66
67// Sıcaklık, nem ve röleyi Home Assistant'a tanıt / announce temperature, humidity and relay to Home Assistant
68void haKesifGonder() {
69  char ek[200];
70  snprintf(ek, sizeof(ek), "\"state_topic\":\"%s\",\"device_class\":\"temperature\",\"unit_of_measurement\":\"°C\",\"state_class\":\"measurement\"", T_SICAKLIK);
71  kesifYayinla("sensor", "sicaklik", "Sıcaklık", ek);
72  snprintf(ek, sizeof(ek), "\"state_topic\":\"%s\",\"device_class\":\"humidity\",\"unit_of_measurement\":\"%%\",\"state_class\":\"measurement\"", T_NEM);
73  kesifYayinla("sensor", "nem", "Nem", ek);
74  snprintf(ek, sizeof(ek), "\"state_topic\":\"%s\",\"command_topic\":\"%s\"", T_DURUM, T_KOMUT);
75  kesifYayinla("switch", "role", "Röle", ek);
76}
77
78// DHT22'yi oku ve değerleri yayınla / read the DHT22 and publish the values
79void olcumGonder() {
80  float t = dht.readTemperature();
81  float h = dht.readHumidity();
82  if (isnan(t) || isnan(h)) {
83    Serial.println("DHT22 okunamadi");
84    return;
85  }
86  char deger[12];
87  snprintf(deger, sizeof(deger), "%.1f", t);     // 23.4 gibi / like 23.4
88  mqtt.publish(T_SICAKLIK, deger, true);
89  snprintf(deger, sizeof(deger), "%.0f", h);     // 45 gibi / like 45
90  mqtt.publish(T_NEM, deger, true);
91  Serial.printf("Sicaklik %.1f C, nem %.0f %%\n", t, h);
92}
93
94// Abone olunan konulara mesaj gelince çalışır / runs when a subscribed topic receives a message
95void mesajGeldi(char* topic, byte* payload, unsigned int length) {
96  // Önce kopyala: yayın yapınca kütüphane aynı tamponu kullanır / copy first: publishing reuses the same buffer
97  String konu = topic;
98  String mesaj;
99  for (unsigned int i = 0; i < length; i++) mesaj += (char)payload[i];
100  mesaj.trim();
101
102  if (konu == T_KOMUT) {
103    if (mesaj == "ON") roleAyarla(true);
104    else if (mesaj == "OFF") roleAyarla(false);
105    else if (mesaj == "TOGGLE") roleAyarla(!roleAcik);
106  } else if (konu == T_HA_DURUM && mesaj == "online") {
107    haKesifGonder();                             // HA yeniden başladı, tanıtımı yenile / HA restarted, announce again
108    mqtt.publish(T_DURUM, roleAcik ? "ON" : "OFF", true);
109  }
110}
111
112bool mqttBaglan() {
113  Serial.print("MQTT baglaniyor... ");
114  // Bağlantı koparsa broker T_BAGLANTI'ya "offline" yazar / if we drop, the broker publishes "offline" to T_BAGLANTI
115  if (!mqtt.connect(ISTEMCI_ID, MQTT_KULLANICI, MQTT_SIFRE, T_BAGLANTI, 1, true, "offline")) {
116    Serial.print("hata, rc=");
117    Serial.println(mqtt.state());
118    return false;
119  }
120  Serial.println("baglandi");
121  mqtt.publish(T_BAGLANTI, "online", true);
122  mqtt.subscribe(T_KOMUT, 1);                    // komutları QoS 1 ile dinle / listen to commands with QoS 1
123  mqtt.subscribe(T_HA_DURUM);
124  haKesifGonder();
125  mqtt.publish(T_DURUM, roleAcik ? "ON" : "OFF", true);
126  return true;
127}
128
129void setup() {
130  Serial.begin(115200);
131  pinMode(ROLE_PIN, OUTPUT);
132  roleAyarla(false);                             // güvenli başlangıç: röle kapalı / safe start: relay off
133  dht.begin();
134
135  WiFi.mode(WIFI_STA);
136  WiFi.begin(WIFI_SSID, WIFI_PASS);
137  Serial.print("Wi-Fi");
138  while (WiFi.status() != WL_CONNECTED) {
139    delay(500);
140    Serial.print(".");
141  }
142  Serial.print(" IP: ");
143  Serial.println(WiFi.localIP());
144
145  mqtt.setServer(MQTT_SUNUCU, MQTT_PORT);
146  mqtt.setCallback(mesajGeldi);
147  mqtt.setBufferSize(1024);                      // keşif JSON'u varsayılan 256 bayta sığmaz / discovery JSON doesn't fit the default 256 bytes
148}
149
150void loop() {
151  if (!mqtt.connected()) {
152    unsigned long simdi = millis();
153    if (sonDeneme == 0 || simdi - sonDeneme >= 5000) {   // 5 sn'de bir dene, loop'u kilitleme / retry every 5 s without blocking
154      sonDeneme = simdi;
155      if (mqttBaglan()) sonOlcum = simdi - OLCUM_ARALIGI;  // bağlanınca hemen ölç / measure right after connecting
156    }
157    return;
158  }
159  mqtt.loop();                                   // gelen komutlar ve keep-alive / incoming commands and keep-alive
160
161  if (millis() - sonOlcum >= OLCUM_ARALIGI) {
162    sonOlcum = millis();
163    olcumGonder();
164  }
165}
LigneRôle
mqtt.connect(ISTEMCI_ID, ..., T_BAGLANTI, 1, true, "offline")Déclare la dernière volonté à la connexion : si l'ESP32 disparaît sans prévenir, le broker écrit un "offline" en retain dans ev/salon/baglanti
mqtt.publish(T_BAGLANTI, "online", true)Passe l'état à "online" dès la connexion ; Home Assistant affiche de nouveau l'appareil comme disponible
mqtt.subscribe(T_KOMUT, 1)Écoute les commandes du relais en QoS 1 ; PubSubClient ne prend en charge que les QoS 0 et 1 pour les abonnements
mqtt.setBufferSize(1024)Agrandit le tampon de paquets au-delà des 256 octets par défaut ; le plus gros paquet de découverte fait environ 355 octets
mqtt.loop()Lit les messages entrants et envoie les paquets keep-alive (PINGREQ) ; doit être appelée à chaque tour de loop
ROLE_AKTIF_LOWLa plupart des modules relais s'enclenchent sur un signal LOW ; si le tien s'enclenche sur HIGH, mets false
OLCUM_ARALIGIIntervalle de mesure ; le DHT22 se lit au plus toutes les 2 secondes, et 30 à 60 secondes sont idéales pour la température d'une pièce

Certains détails du code sont voulus. La fonction mesajGeldi() copie d'abord le topic et le payload dans des String, car PubSubClient utilise un seul tampon pour les messages entrants et sortants : dès que tu appelles publish() dans le callback, les données pointées par topic et payload sont écrasées. Le payload ne se termine pas non plus par un \0 comme une chaîne C, c'est pourquoi nous lisons exactement length caractères. Nous utilisons retain pour les mesures et l'état du relais afin que Home Assistant voie la dernière valeur juste après un redémarrage, sans attendre 30 secondes. Le minutage passe lui aussi par millis() : un long delay() dans loop() retarderait les paquets keep-alive et le broker couperait la connexion. Nous détaillons cette technique dans Arduino millis() ou delay().

N'envoie jamais de messages vers les topics de commande avec le drapeau retain. Si un "ON" en retain reste sur "ev/salon/role/komut", l'ESP32 reçoit cette vieille commande à chaque reconnexion après une coupure de courant ou de Wi-Fi et allume le relais tout seul au milieu de la nuit. Si tu as envoyé une commande en retain par erreur, efface-la en publiant un message retain vide avec mosquitto_pub -r -n -t ev/salon/role/komut. Les interrupteurs MQTT de Home Assistant envoient leurs commandes sans retain par défaut.

L'affichage dans Home Assistant : MQTT Discovery

Home Assistant écoute en permanence les topics commençant par le préfixe homeassistant/. Quand un appareil publie une configuration JSON dans un topic de la forme homeassistant/[composant]/[nœud]/[objet]/config, Home Assistant crée automatiquement l'entité correspondante ; c'est ce qu'on appelle MQTT Discovery. Notre code envoie trois messages : deux pour les capteurs (température et humidité) sous homeassistant/sensor/esp32-salon/... et un pour le relais dans homeassistant/switch/esp32-salon/role/config. Comme ils sont en retain, ils survivent à un redémarrage de Home Assistant. Le code est aussi abonné à homeassistant/status : Home Assistant y écrit "online" au démarrage et l'ESP32 se présente de nouveau. Avec beaucoup d'appareils, la documentation de Home Assistant recommande d'ajouter un petit délai aléatoire avant cette nouvelle présentation.

Champ JSONSignificationNotre valeur
nameNom affiché de l'entité ; le nom de l'appareil est ajouté devantSıcaklık (affiché Salon ESP32 Sıcaklık)
unique_idIdentifiant permanent de l'entité ; sans lui, son nom et sa pièce ne sont pas modifiables dans l'interfaceesp32-salon_sicaklik
state_topicTopic d'où la valeur est lueev/salon/sicaklik
command_topicTopic où sont envoyées les commandes de l'interrupteur (switch)ev/salon/role/komut
device_classDétermine l'icône, les unités possibles et le type de graphiquetemperature, humidity
unit_of_measurementUnité de mesure°C et %
state_classLa valeur measurement active les statistiques à long terme et les graphiquesmeasurement
availability_topicTopic d'où l'état online/offline est lu ; les payloads par défaut sont online et offlineev/salon/baglanti
deviceRegroupe les entités sur une seule fiche d'appareilidentifiers, name, model

Quelques secondes après le téléversement, un appareil nommé "Salon ESP32" apparaît dans Paramètres > Appareils et services > MQTT. Sa fiche contient les capteurs de température et d'humidité ainsi qu'un interrupteur pour le relais ; un clic sur la température ouvre son historique, un clic sur l'interrupteur fait coller le relais. Tu peux ajouter ces entités à un tableau de bord, les exposer aux assistants vocaux ou les utiliser dans des automatisations : par exemple, une règle comme « si le salon dépasse 27 °C, allume le relais du ventilateur et éteins-le sous 25 °C » se crée en quelques clics. Si tu débranches l'ESP32, les entités passent à « Indisponible » au bout de 22 secondes environ au maximum, preuve que la dernière volonté fonctionne. Si tu préfères te passer de la découverte, tu peux aussi déclarer les mêmes entités à la main dans configuration.yaml, en sensor et switch sous mqtt:.

Si tu as changé le nom ou les topics de l'appareil et que d'anciennes entités restent dans Home Assistant, envoie un message retain vide sur le topic config concerné : mosquitto_pub -r -n -t homeassistant/sensor/esp32-salon/sicaklik/config. Home Assistant supprime l'entité, et retire aussi l'appareil s'il ne lui reste aucune autre entité. En donnant un ISTEMCI_ID différent à chaque ESP32, les unique_id deviennent eux aussi différents automatiquement et tu peux ajouter plusieurs pièces sans confusion.

QoS et retain : lequel utiliser et quand ?

La QoS (Quality of Service) définit à quel point tu veux être sûr qu'un message arrive à destination. Un détail important : la QoS s'applique séparément sur deux tronçons. Entre l'émetteur et le broker, c'est la QoS de la publication qui compte ; entre le broker et l'abonné, c'est celle de l'abonnement, et l'abonné obtient la plus faible des deux garanties. PubSubClient ne prend en charge que la QoS 0 en publication et les QoS 0 et 1 en abonnement. Sur le Wi-Fi de la maison, un message perdu en QoS 0 est très rare, mais passer l'abonnement aux commandes en QoS 1 reste une assurance peu coûteuse.

QoSGarantieFonctionnementQuand l'utiliser ?
0Au plus une foisLe message part une seule fois sans accusé de réception ; il peut se perdre si la connexion tombe à ce moment-làMesures fréquentes des capteurs
1Au moins une foisLe destinataire confirme par PUBACK, sinon le message est renvoyé ; il peut arriver deux foisCommandes du relais, alarmes
2Exactement une foisÉchange en quatre étapes avec PUBREC, PUBREL et PUBCOMP ; le niveau le plus lentCompteurs et cas où un doublon pose problème ; non pris en charge par PubSubClient

Le drapeau retain concerne la mémoire plutôt que la livraison : le broker ne garde que le dernier message retain de chaque topic et l'envoie immédiatement à tout nouvel abonné. C'est idéal pour les messages d'« état actuel » comme les valeurs des capteurs, l'état du relais ou la présence en ligne, mais dangereux pour les commandes et les événements ponctuels. La dernière volonté (LWT) le complète : si le broker ne reçoit aucun paquet du client pendant 1,5 fois la période de keep-alive, il considère la connexion comme perdue et publie le message de dernière volonté. Le keep-alive par défaut de PubSubClient est de 15 secondes, donc un ESP32 débranché apparaît "offline" au bout de 22 secondes environ au maximum. Tu peux modifier cette valeur avec une ligne comme mqtt.setKeepAlive(30), mais plus elle est longue, plus tu remarques tard une coupure.

L'alternative sans code : ESPHome

ESPHome est un outil gratuit qui transforme un appareil décrit dans un fichier YAML en firmware prêt à flasher sur l'ESP32 ; tu n'écris pas une seule ligne de C++. Dans Home Assistant, installe ESPHome Device Builder depuis Paramètres > Applications, ouvre son interface et crée une configuration avec l'assistant Nouvel appareil. Le premier téléversement se fait une seule fois par USB : Chrome ou Edge peuvent programmer la carte directement, et si cela ne marche pas, tu peux flasher le fichier téléchargé par l'assistant avec la page ESPHome Web. Toutes les mises à jour suivantes passent par le Wi-Fi (OTA). La configuration ci-dessous reprend le projet Arduino précédent : elle lit le DHT22 sur le GPIO 4 toutes les 30 secondes et expose le relais actif à l'état bas du GPIO 26 comme interrupteur. Les identifiants Wi-Fi et les mots de passe sont lus avec !secret depuis un fichier secrets.yaml séparé :

Code
1esphome:
2  name: salon-sensor               # küçük harf, rakam ve tire / lowercase, digits and hyphens
3  friendly_name: Salon Sensör
4
5esp32:
6  board: esp32dev
7
8logger:
9
10api:                               # Home Assistant ile doğrudan bağlantı / direct link to Home Assistant
11  encryption:
12    key: !secret api_anahtari
13
14ota:
15  - platform: esphome
16    password: !secret ota_sifresi
17
18wifi:
19  ssid: !secret wifi_ssid
20  password: !secret wifi_sifresi
21  ap:                              # Wi-Fi yoksa kendi ağını açar / opens its own network if Wi-Fi fails
22    ssid: "Salon-Sensor"
23    password: "yedek1234"
24
25captive_portal:
26
27sensor:
28  - platform: dht
29    pin: GPIO4
30    model: DHT22
31    update_interval: 30s
32    temperature:
33      name: "Sıcaklık"
34    humidity:
35      name: "Nem"
36
37switch:
38  - platform: gpio
39    name: "Röle"
40    pin:
41      number: GPIO26
42      inverted: true               # aktif LOW röle / active-LOW relay
43    restore_mode: ALWAYS_OFF       # açılışta kapalı / off at boot
44
45# MQTT ile kullanmak için api: bloğunu sil, bunu aç / to use MQTT, delete api: and uncomment this
46# mqtt:
47#   broker: 192.168.1.10
48#   username: esp32
49#   password: !secret mqtt_sifresi

Une différence est à connaître : par défaut, ESPHome n'utilise pas MQTT mais sa propre API native chiffrée. Home Assistant trouve l'appareil tout seul sur le réseau et n'a besoin d'aucun broker. Ne choisis MQTT que si d'autres systèmes comme Node-RED doivent lire les mêmes données, ou si tu n'utilises pas Home Assistant. Pour cela, décommente les lignes mqtt: à la fin du fichier et supprime le bloc api: ; sinon, l'appareil redémarre dès que personne ne s'est connecté à l'API native pendant 15 minutes (c'est le réglage reboot_timeout). En mode MQTT, ESPHome envoie lui-même les messages de découverte pour Home Assistant et les messages online/offline sur salon-sensor/status ; il fait donc automatiquement tout ce que nous avons fait à la main dans le code Arduino.

CritèrePubSubClient (code Arduino)ESPHome (YAML)
ProgrammationTu écris tout toi-même en C++Uniquement du YAML ; le firmware est compilé automatiquement
Ajout dans Home AssistantTu envoies toi-même les JSON de découverteDécouvert automatiquement
SouplesseIllimitée ; n'importe quelle bibliothèque ou logiqueLimitée aux composants existants, mais des centaines de capteurs sont pris en charge ; du C++ peut être ajouté via des lambdas
Mise à jour sans filTu dois ajouter ArduinoOTA toi-mêmeIntégrée
Broker nécessaireOuiNon avec l'API native
Intérêt pédagogiqueApprend le protocole MQTT et la programmationRésultat rapide, cache ce qui se passe en dessous

MQTT avec l'ESP8266 et le Raspberry Pi Pico W

Le code complet ci-dessus fonctionne tel quel sur les cartes ESP8266 NodeMCU et Wemos D1 Mini : quand tu choisis NodeMCU 1.0 dans Outils > Type de carte, le bloc #if defined(ESP8266) sélectionne automatiquement ESP8266WiFi.h au lieu de WiFi.h, ainsi que les broches D2 et D1. Côté Raspberry Pi Pico W, nous utilisons le module MicroPython umqtt.simple. Il n'est pas inclus dans le firmware MicroPython de la Pico W ; installe-le dans Thonny en cherchant umqtt.simple dans Outils > Gérer les paquets, ou tape import mip; mip.install("umqtt.simple") dans le REPL une fois connecté au Wi-Fi. Le module dht nécessaire au DHT22, lui, est fourni avec le firmware. Le code ci-dessous permet à une Pico W placée dans la cuisine d'assurer la même mesure et la même commande du relais. Pour rester court, il ne contient pas les messages de découverte ; pour voir la Pico W dans Home Assistant, publie les mêmes JSON de découverte que dans le code ESP32 avec les topics ev/mutfak, ou déclare les entités à la main sous mqtt: dans configuration.yaml. Enregistre le fichier sous main.py et il se lancera à chaque mise sous tension :

MicroPython
1import network, time, dht
2from machine import Pin
3from umqtt.simple import MQTTClient    # önce mip ile kur / install with mip first
4
5WIFI_SSID = "AgAdi"                    # Wi-Fi adın / your Wi-Fi name
6WIFI_PASS = "Sifre123"                 # Wi-Fi şifren / your Wi-Fi password
7MQTT_SUNUCU = "192.168.1.10"           # broker IP / broker IP
8ISTEMCI_ID = "pico-mutfak"             # benzersiz olmalı / must be unique
9
10T_SICAKLIK = b"ev/mutfak/sicaklik"
11T_NEM = b"ev/mutfak/nem"
12T_KOMUT = b"ev/mutfak/role/komut"
13T_DURUM = b"ev/mutfak/role/durum"
14T_BAGLANTI = b"ev/mutfak/baglanti"
15
16sensor = dht.DHT22(Pin(15))            # DHT22 DATA -> GP15
17role = Pin(14, Pin.OUT, value=1)       # aktif LOW röle kapalı başlar / active-LOW relay starts off
18led = Pin("LED", Pin.OUT)              # Pico W dahili LED / Pico W onboard LED
19
20wlan = network.WLAN(network.STA_IF)
21wlan.active(True)
22wlan.connect(WIFI_SSID, WIFI_PASS)
23while not wlan.isconnected():
24    time.sleep(0.5)
25print("IP:", wlan.ifconfig()[0])
26
27def mesaj_geldi(konu, mesaj):          # ikisi de bytes gelir / both arrive as bytes
28    if konu == T_KOMUT and mesaj in (b"ON", b"OFF"):
29        acik = mesaj == b"ON"
30        role.value(0 if acik else 1)
31        led.value(1 if acik else 0)
32        istemci.publish(T_DURUM, mesaj, retain=True)
33
34istemci = MQTTClient(ISTEMCI_ID, MQTT_SUNUCU, user="esp32", password="mqttSifre", keepalive=60)   # Mosquitto kullanıcısı / Mosquitto user
35istemci.set_callback(mesaj_geldi)
36istemci.set_last_will(T_BAGLANTI, b"offline", retain=True)   # son vasiyet / last will
37
38def baglan():
39    while True:
40        try:
41            if not wlan.isconnected():         # Wi-Fi koptuysa yeniden bağlan / reconnect Wi-Fi if it dropped
42                wlan.connect(WIFI_SSID, WIFI_PASS)
43                time.sleep(5)
44            istemci.connect()
45            istemci.publish(T_BAGLANTI, b"online", retain=True)
46            istemci.publish(T_DURUM, b"OFF" if role.value() else b"ON", retain=True)
47            istemci.subscribe(T_KOMUT)
48            print("MQTT baglandi")
49            return
50        except Exception as e:         # MQTTException(5): yetki yok / not authorized
51            print("MQTT hatasi:", e)
52            time.sleep(5)
53
54baglan()
55son = time.ticks_add(time.ticks_ms(), -30000)   # ilk ölçüm hemen / first reading right away
56while True:
57    try:
58        istemci.check_msg()            # bekleyen komut var mı? / any pending command?
59        if time.ticks_diff(time.ticks_ms(), son) >= 30000:
60            son = time.ticks_ms()
61            try:
62                sensor.measure()
63            except OSError:
64                print("DHT22 okunamadi")
65                istemci.ping()         # veri yoksa da bağlantıyı canlı tut / keep the link alive without data
66            else:
67                istemci.publish(T_SICAKLIK, "{:.1f}".format(sensor.temperature()).encode(), retain=True)
68                istemci.publish(T_NEM, "{:.0f}".format(sensor.humidity()).encode(), retain=True)
69    except OSError:
70        print("Baglanti koptu, yeniden baglaniliyor")
71        time.sleep(5)
72        baglan()
73    time.sleep_ms(100)

Idées de projets ESP32 MQTT

  • Carte des températures pièce par pièce : Place dans chaque pièce un ESP32 avec un DHT22 ou un BME280 et suis toute la maison sur un seul graphique grâce à un abonnement à ev/+/sicaklik.
  • Lampe et prise connectées : Relie le relais à une automatisation Home Assistant qui l'allume au coucher du soleil et l'éteint à minuit.
  • Capteur de porte et de fenêtre : Avec un interrupteur reed, envoie un message MQTT à l'ouverture de la porte et reçois une notification quand personne n'est à la maison.
  • Éclairage de couloir sur détection : Laisse un capteur PIR publier les mouvements et une automatisation Home Assistant allumer la lumière.
  • Station d'arrosage : Publie la valeur du capteur d'humidité du sol et lance la pompe par une commande MQTT quand la terre est sèche.
  • Suivi de consommation : Mesure le courant d'un appareil avec un capteur de courant ACS712 et trace sa consommation quotidienne.
  • Capteur sur pile : Construis un nœud qui mesure, envoie la valeur par MQTT puis se rendort ; les détails sont dans ESP32 Deep Sleep.

Erreurs ESP32 MQTT fréquentes et solutions

Symptôme ou messageCauseSolution
rc=-2 en permanenceIP ou port du broker erronés, broker arrêté ou Mosquitto en mode local uniquementVérifie l'IP, ajoute listener 1883 à la configuration, autorise le port 1883 dans le pare-feu
rc=5Nom d'utilisateur ou mot de passe incorrect, ou tentative de connexion sans identifiantsTeste le mot de passe depuis l'ordinateur avec mosquitto_sub ; recrée l'utilisateur si besoin
Se connecte, décroche au bout de quelques secondes, en boucleDeux appareils utilisent le même client ID ; Mosquitto écrit "Client esp32-salon already connected, closing old connection." dans son journalDonne à chaque appareil un ISTEMCI_ID unique
Les messages de découverte ne partent pas, publish() renvoie falseLe tampon de PubSubClient fait 256 octets par défaut et le JSON n'y tient pasAppelle mqtt.setBufferSize(1024) dans setup()
rc=-3 fréquentUn long delay() dans loop() empêche l'envoi des keep-alive, ou le signal Wi-Fi est faibleGère le temps avec millis() et rapproche la carte de la box
Les commandes n'arrivent pas à l'ESP32Le nom du topic diffère par la casse ou l'orthographe, ou subscribe() n'est pas refait après reconnexionVérifie le topic avec mosquitto_sub ; place les lignes subscribe() dans la fonction de connexion
Le relais s'allume tout seul au démarrageUn ancien message retain traîne sur le topic de commandeEfface-le avec mosquitto_pub -r -n -t ev/salon/role/komut
Entités « Indisponible » dans Home AssistantLe topic de disponibilité indique offline ou online est écrit autrementÉcoute ev/salon/baglanti et vérifie que le code publie online après la connexion
Caractères bizarres à la place de la valeurLe payload ne se termine pas par \0 et a été lu sans utiliser lengthCopie le payload avec une boucle jusqu'à length
L'appareil ESPHome redémarre toutes les 15 minutesEn mode MQTT, le bloc api: est encore là mais Home Assistant ne s'y connecte jamaisSupprime le bloc api: ou ajoute reboot_timeout: 0s
Garde un ordre quand tu cherches une panne : vérifie d'abord la connexion Wi-Fi et l'adresse IP dans le moniteur série, observe ensuite sur l'ordinateur avec mosquitto_sub -v -t "#" ce qui arrive réellement au broker, et regarde Home Assistant seulement à la fin. Si le message est visible sur le broker mais pas dans Home Assistant, le problème vient du JSON de découverte ; s'il n'arrive même pas au broker, il est côté ESP32. Si tu bloques dès le Wi-Fi, consulte L'ESP32 ne se connecte pas au Wi-Fi, et si la carte redémarre quand le relais colle, ESP32 Brownout et Guru Meditation.

Avec un broker, quelques topics et PubSubClient, ton ESP32 est devenu un appareil domotique qui parle la même langue que le reste de la maison. Tu peux ajouter de nouveaux capteurs, d'autres pièces et d'autres cartes comme la Pico W, puis tout gérer depuis un seul tableau de bord Home Assistant. Dans l'application BlueGrays, tu trouveras des projets comme la connexion Wi-Fi de l'ESP32, la mesure de température et d'humidité avec le DHT22, l'éclairage intelligent avec PIR et relais, le contrôle en temps réel par WebSocket et l'arrosage intelligent des plantes, pas à pas avec schémas de câblage et code.

Questions fréquentes

Qu'est-ce que MQTT et à quoi ça sert ?

MQTT est un protocole de messagerie léger dans lequel les appareils envoient et reçoivent des messages via un broker en utilisant des noms de topics. Comme il consomme peu de bande passante et d'énergie, il est idéal pour que de petits appareils comme l'ESP32 envoient des données de capteurs et reçoivent des commandes. Home Assistant, Node-RED et la plupart des systèmes IoT industriels parlent MQTT.

Quel port utilise MQTT ?

Le MQTT non chiffré utilise par défaut le port 1883 et le MQTT chiffré en TLS le port 8883. Le port WebSocket utilisé pour les connexions depuis un navigateur dépend du broker ; sur le broker Mosquitto de Home Assistant, c'est le 1884. Sur un réseau domestique, l'ESP32 se connecte généralement au 1883.

MQTT a-t-il besoin d'internet ?

Non. Si le broker tourne chez toi, sur un Raspberry Pi ou dans Home Assistant, le trafic entre l'ESP32 et le broker reste entièrement sur ton réseau local ; capteurs et relais continuent de fonctionner même si internet est coupé. Internet n'est nécessaire que pour un accès depuis l'extérieur ou pour utiliser un broker dans le cloud.

Pourquoi mon ESP32 n'apparaît-il pas dans Home Assistant ?

Les causes les plus fréquentes sont un message de découverte qui ne tient pas dans le tampon de 256 octets de PubSubClient, un topic config mal écrit ou une erreur de guillemets dans le JSON. Écoute homeassistant/# avec mosquitto_sub pour vérifier que le message arrive au broker et assure-toi que le code contient la ligne mqtt.setBufferSize(1024). L'intégration MQTT de Home Assistant doit aussi être connectée au même broker.

Faut-il choisir ESPHome ou MQTT avec Arduino ?

Si ton but est d'obtenir vite un appareil domotique qui fonctionne, ESPHome demande moins d'efforts : tu écris du YAML, l'appareil apparaît tout seul dans Home Assistant et se met à jour sans fil. Si tu veux apprendre le protocole MQTT, écrire ta propre logique ou travailler avec d'autres systèmes que Home Assistant, Arduino avec PubSubClient est plus souple. Les deux cohabitent sans problème dans la même maison.

Quelle est la différence entre les QoS 0, 1 et 2 de MQTT ?

La QoS 0 envoie le message une fois sans attendre d'accusé de réception, la QoS 1 le renvoie jusqu'à confirmation mais il peut arriver deux fois, et la QoS 2 garantit par un échange en quatre étapes qu'il arrive exactement une fois. La QoS 0 suffit pour les mesures de capteurs et la QoS 1 pour les commandes. PubSubClient ne peut publier qu'en QoS 0 et s'abonner en QoS 0 ou 1.

Voir tous les projets
Clignotement LED avec ESP32
#103Débutant

Clignotement LED avec ESP32

Enseigne l'utilisation de base des sorties GPIO avec l'ESP32. Nous obtenons un effet de clignotement en allumant et éteignant une LED à partir de la broche numérique. Version ESP32 du projet blink classique sur Arduino UNO ; les commandes de base de blink dans l'environnement Arduino restent les mêmes, mais le brochage et les niveaux GPIO de 3,3 V de l'ESP32 diffèrent de ceux de l'Arduino UNO.

4.7(37)
99
Connexion Wi-Fi STA ESP32 (avec écran LCD)
#127Avancé

Connexion Wi-Fi STA ESP32 (avec écran LCD)

Dans ce projet, nous connectons l'ESP32 au réseau Wi-Fi domestique en mode Station (STA) de manière sécurisée et tolérante aux pannes. Nous isolons SSID/mot de passe dans un fichier secrets.h pour empêcher leur fuite sur Git, mettons en place une reconnexion automatique, et affichons le niveau RSSI et l'adresse IP sur un écran LCD I2C. La LED intégrée sert d'indicateur d'état.

4.4(21)
34
ESP32 DHT22 Température et humidité (avec écran LCD)
#117Intermédiaire

ESP32 DHT22 Température et humidité (avec écran LCD)

Il s'agit d'un projet permettant de mesurer la température ambiante et le taux d'humidité à l'aide d'un capteur DHT22 et d'afficher ces données en temps réel sur un écran LCD I2C 16x2. Les données du capteur sont lues à l'aide du protocole one-wire grâce à la bibliothèque Adafruit DHT. Ce projet constitue la base des stations météo IoT, de la domotique ou des systèmes de surveillance de l'environnement dans les serres.

4.8(38)
56
Éclairage Intelligent ESP32 (PIR + LDR + Relais + OLED)
#141Avancé
Premium

Éclairage Intelligent ESP32 (PIR + LDR + Relais + OLED)

Transformez votre couloir, votre salle de bain ou votre garde-manger en éclairage intelligent avec l'ESP32 ! En utilisant un capteur de mouvement PIR, un capteur de lumière LDR et un module relais, nous construisons le scénario classique "la lumière s'allume lorsqu'un mouvement est détecté dans l'obscurité" — si l'environnement est déjà lumineux, le mouvement N'ACTIVE PAS la lumière, économisant ainsi de l'énergie pendant la journée. La lumière reste allumée pendant 30 secondes ; si le mouvement

4.3(6)
11
Compteur ESP32 WebSocket (2 boutons + écran LCD + affichage Web en temps réel)
#130Avancé
Premium

Compteur ESP32 WebSocket (2 boutons + écran LCD + affichage Web en temps réel)

Dans ce projet, deux boutons reliés à l'ESP32 (GPIO 5 incrémente, GPIO 4 décrémente) modifient un compteur. La valeur se met à jour instantanément sur un écran LCD I2C 16x2 et, grâce au support WebSocket d'ESPAsyncWebServer, dans tous les navigateurs connectés sans recharger la page. Au lieu du polling HTTP, une seule connexion persistante est utilisée et l'ESP32 envoie la nouvelle valeur à tous avec ws.textAll().

4.5(14)
23
ESP32 mDNS : accès à l'appareil via bluegrays-esp.local (avec écran LCD)
#131Avancé
Premium

ESP32 mDNS : accès à l'appareil via bluegrays-esp.local (avec écran LCD)

Dans ce projet, en ajoutant un service mDNS (Multicast DNS) à l'ESP32, nous permettons d'accéder à l'appareil via un nom d'hôte lisible, tel que bluegrays-esp.local, plutôt qu'à l'aide d'une adresse IP. Même si l'adresse IP attribuée par le DHCP venait à changer, vous pourrez toujours accéder à l'appareil sous le même nom. En exécutant également un petit serveur web sur l'appareil, nous envoyons des commandes de contrôle des LED depuis un navigateur via l'adresse http://bluegrays-esp.local/.

4.8(14)
23
Système d'Alarme de Mouvement ESP32 (PIR + Buzzer + LED + Telegram)
#145Avancé
Premium

Système d'Alarme de Mouvement ESP32 (PIR + Buzzer + LED + Telegram)

Un système d'alarme de sécurité intelligent qui active le buzzer et la LED lorsque le capteur PIR détecte un mouvement, tout en envoyant une notification instantanée au propriétaire via Telegram. Il intègre un délai d'attente de 30 secondes pour limiter la fréquence des alarmes répétées ; ce mécanisme ne vérifie pas la validité des détections du capteur PIR et n'élimine pas les faux déclenchements. Idéal pour la sécurité domestique, la surveillance de garage, d'entrepôts ou de bureaux. Avec l'ES

0.0(0)
9