Guide · 17 min di lettura

ESP32 MQTT: guida con Mosquitto, Home Assistant ed ESPHome

Guida ESP32 MQTT: installa Mosquitto, pubblica dati dei sensori e comanda un relè con PubSubClient, discovery in Home Assistant, YAML di ESPHome e QoS.

La coppia ESP32 e MQTT è il modo più diffuso per far dialogare i sensori e i relè di casa tra loro e con un sistema domotico come Home Assistant. MQTT è un protocollo di messaggistica leggero pensato per i piccoli dispositivi: l'ESP32 deposita la temperatura misurata in un topic come "ev/salon/sicaklik" e ogni programma che ascolta quel topic riceve il valore all'istante. Allo stesso modo, quando premi un pulsante nell'app di Home Assistant sul telefono, il comando "ON" raggiunge l'ESP32 in molto meno di un secondo e fa scattare il relè. A differenza di HTTP non apre una nuova connessione a ogni richiesta; lavora su un'unica connessione aperta con intestazioni di appena due byte, quindi è veloce e pesa poco sia sul Wi-Fi sia sul processore.

In questa guida costruirai da zero un nodo domotico funzionante. Prima imparerai i concetti MQTT di broker, topic, publish e subscribe, poi installerai il broker Mosquitto in Home Assistant o su un Raspberry Pi. Quindi userai la libreria PubSubClient per pubblicare dall'ESP32 temperatura e umidità di un DHT22, ascoltare i comandi per un relè e aggiungere MQTT Discovery, così il dispositivo comparirà da solo in Home Assistant. Vedremo anche QoS e retain, il messaggio di ultime volontà (LWT) che segna il dispositivo come "non disponibile" quando cade la connessione, l'alternativa ESPHome che fa lo stesso senza scrivere C++, le differenze con ESP8266 e Raspberry Pi Pico W e gli errori più comuni uno per uno.

Scheda di sviluppo ESP32 collegata a Home Assistant tramite MQTT
Grazie al Wi-Fi integrato, l'ESP32 si collega direttamente al broker MQTT della rete di casa; i dati dei sensori e i comandi del relè viaggiano sulla stessa connessione.

Cos'è MQTT e come funziona?

MQTT (Message Queuing Telemetry Transport) si basa sul modello pubblicazione/sottoscrizione. Al centro c'è un server chiamato broker; l'ESP32, Home Assistant, il tuo telefono o un programma sul computer si collegano a lui come client. I client non si conoscono e non sanno gli indirizzi IP degli altri: uno pubblica un messaggio in un topic e il broker lo inoltra a tutti quelli iscritti a quel topic. Immaginalo come un ufficio postale: l'ESP32 imbuca una lettera nella casella "ev/salon/sicaklik" e Home Assistant, che tiene d'occhio quella casella, la riceve subito. Poiché è sempre il client ad aprire la connessione, l'ESP32 non ha bisogno di un IP fisso né di porte aperte sul router; deve solo conoscere l'indirizzo del broker.

ConcettoA cosa serveEsempio
BrokerServer che riceve i messaggi e li distribuisce agli iscrittiMosquitto, il broker Mosquitto di Home Assistant
ClientQualsiasi dispositivo o programma collegato al broker; ognuno ha un identificativo univoco (client ID)ESP32, Home Assistant, MQTT Explorer
Topic (argomento)Indirizzo del messaggio, fatto di livelli separati da barreev/salon/sicaklik
Publish (pubblicare)Inviare un messaggio a un topicMandare il valore "23.4" a ev/salon/sicaklik
Subscribe (iscriversi)Registrarsi per ricevere i messaggi di un topicL'ESP32 che ascolta ev/salon/role/komut
Payload (contenuto)Contenuto del messaggio: testo, numero o JSONON, 23.4, {"sicaklik":23.4}
RetainIl broker conserva l'ultimo messaggio di un topic e lo consegna subito ai nuovi iscrittiStato del relè: ON
LWT (ultime volontà)Messaggio che il broker pubblica a nome di un client che si scollega senza preavvisoev/salon/baglanti: offline
QoSLivello di garanzia di consegna del messaggio (0, 1 o 2)QoS 1 per i comandi del relè

Perché MQTT? Confronto con web server, Blynk e Telegram

MetodoVantaggiSvantaggiIdeale per
MQTT + Home AssistantLocale e veloce, bidirezionale; centinaia di dispositivi in un'unica dashboard, automazioniServe un brokerGestire tutta la casa da un unico punto
Web server sull'ESP32Nessun server aggiuntivo, si apre nel browserOgni dispositivo ha la sua pagina, niente automazioni tra dispositiviPannello di controllo di un solo dispositivo
Blynk IoTDashboard per telefono già pronta, accesso via internetDipende dal cloud, limiti nel piano gratuitoPrototipi mobili rapidi
Bot TelegramNotifiche istantanee gratuite, nessuna porta da aprireNiente grafici né dashboardAllarmi e comandi semplici
ESP-NOWLe schede ESP comunicano senza router né brokerSolo tra schede ESP, non arriva direttamente a Home AssistantPortare i dati di un sensore a batteria fino a un gateway

In breve, MQTT dà il meglio quando i dispositivi aumentano: quando aggiungi un nuovo sensore non tocchi nessun codice esistente, inizi semplicemente a pubblicare in un nuovo topic. Se vuoi comandare un solo dispositivo dal browser, la guida ESP32 Async Web Server e WebSocket ti porta al risultato prima; per le notifiche sul telefono c'è Bot Telegram con ESP32 e per una dashboard mobile già pronta Blynk con ESP32. Per un sensore in giardino fuori dalla portata del router, una buona soluzione è portare i dati con ESP-NOW a un ESP32 gateway collegato a MQTT.

Struttura dei topic MQTT e caratteri jolly

I topic somigliano a percorsi di cartelle: "ev/salon/sicaklik" (in turco casa/soggiorno/temperatura) ha tre livelli e distingue maiuscole e minuscole, quindi "Ev/Salon" ed "ev/salon" sono due topic diversi. Non iniziare con una barra ("/ev/salon" crea un primo livello vuoto) ed evita spazi e lettere accentate; bastano lettere semplici, cifre, trattini e trattini bassi. Quando ti iscrivi puoi usare due caratteri jolly: + sostituisce esattamente un livello ("ev/+/sicaklik" restituisce la temperatura di tutte le stanze), mentre # copre tutto ciò che segue e può stare solo alla fine ("ev/#" restituisce tutti i messaggi della casa). I jolly valgono solo per le iscrizioni; un messaggio si pubblica sempre in un topic preciso. I topic che iniziano con $ (come $SYS) sono riservati alle statistiche del broker e non rientrano in un'iscrizione a #. Per il progetto di questa guida useremo questa struttura:

TopicPubblicato daAscoltato daRetain
ev/salon/sicaklikESP32 (ogni 30 secondi)Home AssistantSì
ev/salon/nemESP32 (ogni 30 secondi)Home AssistantSì
ev/salon/role/komutHome Assistant, telefono, automazioniESP32No
ev/salon/role/durumESP32 (a ogni cambiamento)Home AssistantSì
ev/salon/baglantiESP32 (online), broker (offline)Home AssistantSì
homeassistant/statusHome Assistant (online all'avvio)ESP32No

Installare un broker MQTT: Mosquitto

Il broker MQTT gratuito più diffuso è Eclipse Mosquitto; anche su un Raspberry Pi gestisce senza fatica centinaia di messaggi al secondo. Ci sono tre modi semplici per installarlo: l'app ufficiale Mosquitto broker se usi Home Assistant OS, il pacchetto apt su un Raspberry Pi o un computer Linux separato, oppure l'installer di Mosquitto su Windows. Qualunque strada scegli, il broker usa la porta 1883 per MQTT non cifrato e la 8883 per MQTT cifrato con TLS, e deve solo trovarsi nella stessa rete di casa dell'ESP32. In Home Assistant l'installazione funziona così:

  1. In Home Assistant apri Impostazioni > App (nelle versioni precedenti questa sezione si chiama Componenti aggiuntivi o Add-on), premi Installa app e scegli Mosquitto broker dall'elenco.
  2. Premi Installa; al termine premi Avvia e lascia attiva l'opzione di avvio automatico.
  3. Crea un utente apposito per l'ESP32: in Impostazioni > Persone > Utenti aggiungi un utente "esp32" con una password robusta. Se non vedi questa scheda, attiva la modalità avanzata nel tuo profilo. I nomi "homeassistant" e "addons" sono riservati al broker, non usarli.
  4. Nella pagina Impostazioni > Dispositivi e servizi l'integrazione MQTT di solito compare da sola come "Rilevata"; premi Configura e conferma. Se non compare, cerca MQTT con Aggiungi integrazione e scegli l'opzione che configura Mosquitto automaticamente.
  5. Nel codice dell'ESP32 inserirai come indirizzo del broker l'IP di Home Assistant (per esempio 192.168.1.10), come porta 1883 e l'utente appena creato.

Su una macchina Linux come un Raspberry Pi o Ubuntu bastano pochi comandi. Installa il broker e gli strumenti di test con sudo apt install mosquitto mosquitto-clients. Crea l'utente "esp32" con sudo mosquitto_passwd -c /etc/mosquitto/passwd esp32 e digita la password due volte; l'opzione -c crea il file da zero, quindi non usarla quando aggiungi un secondo utente, altrimenti quelli precedenti vengono cancellati. Poi crea un file locale.conf nella cartella /etc/mosquitto/conf.d/, scrivi le tre righe qui sotto e riavvia il servizio con sudo systemctl restart mosquitto. Su Windows basta aggiungere le stesse righe al file mosquitto.conf nella cartella di installazione e riavviare il servizio Mosquitto Broker.

RigaSignificato
listener 1883Ascolta sulla porta 1883 su tutte le interfacce di rete; senza questa riga Mosquitto 2.x accetta solo connessioni dallo stesso computer
allow_anonymous falseRifiuta le connessioni senza nome utente e password; nella 2.x è già il valore predefinito, ma scriverlo è una buona abitudine
password_file /etc/mosquitto/passwdUsa il file di password creato con mosquitto_passwd; le password vi sono salvate come hash
Se nella configurazione non è definito alcun listener, Mosquitto 2.0 e successivi ascoltano solo su 127.0.0.1 e scrivono nel log l'avviso "Starting in local only mode. Connections will only be possible from clients running on this machine.". In questo caso l'ESP32 non riesce a collegarsi e ottieni l'errore rc=-2. D'altra parte, non aprire mai la porta 1883 verso internet sul router (niente port forwarding): il traffico MQTT non cifrato può essere letto lungo il percorso e i relè di casa potrebbero finire in mani altrui. Se ti serve l'accesso dall'esterno, usa una VPN o le soluzioni di accesso remoto di Home Assistant.

Prima di passare all'ESP32, prova il broker dal computer; separare subito i problemi del broker da quelli del codice ti fa risparmiare molto tempo. In un terminale inizia ad ascoltare tutti i topic della casa con mosquitto_sub -h 192.168.1.10 -u esp32 -P latuapassword -t "ev/#" -v. In un secondo terminale scrivi mosquitto_pub -h 192.168.1.10 -u esp32 -P latuapassword -t ev/salon/test -m ciao. Se nel primo terminale compare la riga "ev/salon/test ciao", il broker funziona e la password è giusta. L'opzione -v stampa il topic davanti a ogni messaggio, mentre l'opzione -r invia il messaggio come retain.

Se la riga di comando non fa per te, il programma gratuito MQTT Explorer mostra tutti i topic del broker in una vista ad albero, con gli ultimi valori e i contrassegni retain. Anche in Home Assistant puoi andare in Impostazioni > Dispositivi e servizi > MQTT > Configura, scrivere ev/# nel campo "Ascolta un argomento" e iniziare ad ascoltare, e usare la sezione "Pubblica un pacchetto" per inviare comandi all'ESP32 a mano.

Materiale necessario e schema di collegamento

Per il progetto ti servono una scheda di sviluppo ESP32, un sensore di temperatura e umidità DHT22, un modulo relè che si possa comandare a 3,3 V, una breadboard e dei cavetti jumper. Il DHT22 è più preciso del DHT11: misura la temperatura con ±0,5 °C e l'umidità con circa ±2–5 % e funziona da -40 a 80 °C; spieghiamo la famiglia di sensori in dettaglio in Sensore di temperatura e umidità DHT11. Se hai un DHT11, cambia semplicemente DHT22 in DHT11 nel codice. Per il primo test di connessione bastano un ESP32 e un cavo USB; sensore e relè puoi aggiungerli dopo.

ESP32
ESP32
DHT22
DHT22
Modulo relè
Modulo relè
CollegamentoESP32ESP8266 (NodeMCU)Raspberry Pi Pico W
DHT22 VCC3V33V33V3(OUT)
DHT22 DATAGPIO 4D2 (GPIO 4)GP15
DHT22 GNDGNDGNDGND
Relè VCCVIN (5V)VIN (5V)VBUS (5V)
Relè INGPIO 26D1 (GPIO 5)GP14
Relè GNDGNDGNDGND
I pin di ESP32, ESP8266 e Pico lavorano a 3,3 V e non tollerano i 5 V; per questo alimentiamo il DHT22 dal pin 3V3. I moduli DHT22 a tre pin di solito hanno già una resistenza di pull-up sulla scheda; se usi il sensore nudo a quattro piedini, aggiungi una resistenza da 4,7–10 kΩ tra DATA e VCC. Se con il relè commuti un carico di rete a 230 V, fai tutti i collegamenti con la spina staccata e chiedi aiuto a un adulto; i dettagli sono in Cos'è un modulo relè?. Puoi vedere tutti i pin della tua scheda nello strumento Pinout.

Installare PubSubClient nell'Arduino IDE

  1. Se nell'Arduino IDE non è ancora installato il pacchetto delle schede ESP32, installalo prima; i passaggi sono in Cos'è l'ESP32?.
  2. Apri Strumenti > Gestisci librerie, scrivi PubSubClient nella casella di ricerca e installa la libreria di Nick O'Leary. Il codice di questa guida è stato compilato con la versione 2.8.
  3. Nella stessa finestra cerca DHT sensor library e installa la libreria di Adafruit; quando ti chiede delle dipendenze, scegli Install all così viene installata anche Adafruit Unified Sensor.
  4. Se hai problemi a installare le librerie, consulta la guida Come aggiungere librerie in Arduino.

Primo test: collegare l'ESP32 al broker MQTT

Prima di aggiungere i sensori verifichiamo con il codice più semplice possibile che dati del Wi-Fi, indirizzo del broker e password siano corretti. Il codice qui sotto si collega al broker, pubblica "merhaba" (ciao) nel topic "test/esp32/durum" e stampa nel Monitor seriale ogni messaggio che arriva su "test/esp32/komut". Sostituisci nome del Wi-Fi, password, IP del broker e utente MQTT con i tuoi, carica il codice e apri il Monitor seriale a 115200 baud:

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}

Quando nel Monitor seriale vedi "baglandi" (connesso), invia da un terminale del computer mosquitto_pub -h 192.168.1.10 -u esp32 -P latuapassword -t test/esp32/komut -m ciao; in pochi millisecondi nel Monitor seriale compare la riga "Mesaj [test/esp32/komut] ciao". Se la connessione non riesce, il codice stampa un codice di errore con mqtt.state() e riprova dopo 5 secondi. Questi codici ti dicono esattamente dove sta il problema:

rcNome in PubSubClientSignificato e soluzione
-4MQTT_CONNECTION_TIMEOUTIl broker non ha risposto in tempo; rete debole o broker sovraccarico
-3MQTT_CONNECTION_LOSTUna connessione già stabilita è caduta; di solito perché loop() non è stato chiamato a lungo o il Wi-Fi è sparito
-2MQTT_CONNECT_FAILEDLa connessione TCP non si è mai aperta: IP o porta sbagliati, broker spento, Mosquitto in modalità solo locale o un firewall che blocca la 1883
-1MQTT_DISCONNECTEDLa connessione è stata chiusa correttamente (è stato chiamato disconnect) oppure non è mai stata aperta
2MQTT_CONNECT_BAD_CLIENT_IDIdentificativo del client rifiutato; è stato usato un client ID vuoto o non valido
4MQTT_CONNECT_BAD_CREDENTIALSNome utente o password errati (alcuni broker restituiscono questo codice)
5MQTT_CONNECT_UNAUTHORIZEDNon autorizzato; Mosquitto restituisce questo codice sia con una password sbagliata sia quando si tenta di collegarsi senza credenziali

Pubblicare i dati dei sensori e ascoltare i comandi del relè con l'ESP32

Ora costruiamo il progetto vero e proprio. Il codice qui sotto legge il DHT22 ogni 30 secondi e pubblica temperatura e umidità con il flag retain, comanda il relè con i comandi ON, OFF e TOGGLE che arrivano su "ev/salon/role/komut" e comunica il nuovo stato del relè su "ev/salon/role/durum". Quando si collega lascia al broker un messaggio di ultime volontà, si presenta a Home Assistant con MQTT Discovery e, se la connessione cade, riprova ogni 5 secondi senza bloccare loop(). Grazie al blocco #if defined(ESP8266) in cima, lo stesso codice si compila senza modifiche anche su 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}
RigaCosa fa
mqtt.connect(ISTEMCI_ID, ..., T_BAGLANTI, 1, true, "offline")Registra le ultime volontà durante la connessione: se l'ESP32 cade senza preavviso, il broker scrive un "offline" retain in ev/salon/baglanti
mqtt.publish(T_BAGLANTI, "online", true)Porta lo stato a "online" appena connesso; Home Assistant mostra di nuovo il dispositivo come disponibile
mqtt.subscribe(T_KOMUT, 1)Ascolta i comandi del relè con QoS 1; PubSubClient supporta solo QoS 0 e 1 nelle iscrizioni
mqtt.setBufferSize(1024)Ingrandisce il buffer dei pacchetti oltre i 256 byte predefiniti; il pacchetto di discovery più grande è di circa 355 byte
mqtt.loop()Legge i messaggi in arrivo e invia i pacchetti keep-alive (PINGREQ); va chiamato a ogni giro di loop
ROLE_AKTIF_LOWLa maggior parte dei moduli relè scatta con un segnale LOW; se il tuo scatta con HIGH, impostalo a false
OLCUM_ARALIGIOgni quanto misurare; il DHT22 si può leggere al massimo ogni 2 secondi e per la temperatura di una stanza l'ideale è 30–60 secondi

Alcuni dettagli del codice sono voluti. La funzione mesajGeldi() copia per prima cosa topic e payload in delle String, perché PubSubClient usa un unico buffer per i messaggi in entrata e in uscita: appena chiami publish() dentro la callback, i dati a cui puntano topic e payload vengono sovrascritti. Il payload inoltre non termina con \0 come una stringa C, perciò leggiamo esattamente length caratteri. Usiamo retain per le letture e per lo stato del relè così Home Assistant vede l'ultimo valore subito dopo un riavvio, senza aspettare 30 secondi. Anche i tempi sono gestiti con millis(): un lungo delay() dentro loop() ritarderebbe i pacchetti keep-alive e il broker chiuderebbe la connessione. Spieghiamo questa tecnica in dettaglio in Arduino millis() e delay().

Non inviare mai messaggi ai topic di comando con il flag retain. Se su "ev/salon/role/komut" resta un "ON" retain, l'ESP32 riceve quel vecchio comando ogni volta che si ricollega dopo un blackout o un calo del Wi-Fi e accende il relè da solo nel cuore della notte. Se hai inviato per errore un comando retain, cancellalo pubblicando un messaggio retain vuoto con mosquitto_pub -r -n -t ev/salon/role/komut. Gli interruttori MQTT di Home Assistant inviano i comandi senza retain per impostazione predefinita.

Come appare in Home Assistant: MQTT Discovery

Home Assistant ascolta di continuo i topic che iniziano con il prefisso homeassistant/. Quando un dispositivo pubblica una configurazione JSON in un topic della forma homeassistant/[componente]/[nodo]/[oggetto]/config, Home Assistant crea automaticamente l'entità; questo meccanismo si chiama MQTT Discovery. Il nostro codice invia tre messaggi: due per i sensori (temperatura e umidità) in homeassistant/sensor/esp32-salon/... e uno per il relè in homeassistant/switch/esp32-salon/role/config. Essendo retain, sopravvivono anche a un riavvio di Home Assistant. Il codice è inoltre iscritto a homeassistant/status: all'avvio Home Assistant ci scrive "online" e l'ESP32 si ripresenta. Con molti dispositivi, la documentazione di Home Assistant consiglia di aggiungere un piccolo ritardo casuale prima di questa nuova presentazione.

Campo JSONSignificatoIl nostro valore
nameNome visualizzato dell'entità; davanti viene aggiunto il nome del dispositivoSıcaklık (appare come Salon ESP32 Sıcaklık)
unique_idIdentificativo permanente dell'entità; senza, nome e area non si possono modificare dall'interfacciaesp32-salon_sicaklik
state_topicTopic da cui si legge il valoreev/salon/sicaklik
command_topicTopic a cui si inviano i comandi dell'interruttore (switch)ev/salon/role/komut
device_classStabilisce icona, unità disponibili e tipo di graficotemperature, humidity
unit_of_measurementUnità di misura°C e %
state_classIl valore measurement attiva le statistiche a lungo termine e i graficimeasurement
availability_topicTopic da cui si legge lo stato online/offline; i payload predefiniti sono online e offlineev/salon/baglanti
deviceRaggruppa le entità in un'unica scheda dispositivoidentifiers, name, model

Pochi secondi dopo il caricamento del codice, in Impostazioni > Dispositivi e servizi > MQTT compare un dispositivo chiamato "Salon ESP32". La sua scheda contiene i sensori di temperatura e umidità e un interruttore per il relè; toccando la temperatura si apre lo storico, azionando l'interruttore il relè scatta. Puoi aggiungere queste entità a una dashboard, esporle agli assistenti vocali o usarle nelle automazioni: per esempio una regola come "se il soggiorno supera i 27 °C accendi il relè del ventilatore e spegnilo sotto i 25 °C" si crea in pochi clic. Se scolleghi l'ESP32, le entità passano a "Non disponibile" al massimo dopo circa 22 secondi, segno che le ultime volontà funzionano. Se preferisci non usare la discovery, puoi anche definire le stesse entità a mano nel file configuration.yaml, come sensor e switch sotto mqtt:.

Se hai cambiato nome o topic del dispositivo e in Home Assistant restano vecchie entità, invia un messaggio retain vuoto al relativo topic config: mosquitto_pub -r -n -t homeassistant/sensor/esp32-salon/sicaklik/config. Home Assistant elimina l'entità e rimuove anche il dispositivo se non gli restano altre entità. Dando a ogni ESP32 un ISTEMCI_ID diverso, anche gli unique_id cambiano automaticamente e puoi aggiungere più stanze senza confusione.

QoS e retain: quale usare e quando?

La QoS (Quality of Service) stabilisce quanto vuoi essere sicuro che un messaggio arrivi a destinazione. Un dettaglio importante: la QoS si applica separatamente su due tratte. Tra chi pubblica e il broker vale la QoS della pubblicazione, tra il broker e l'iscritto quella dell'iscrizione; l'iscritto ottiene la garanzia più bassa delle due. PubSubClient supporta solo QoS 0 in pubblicazione e QoS 0 e 1 nelle iscrizioni. Sul Wi-Fi di casa un messaggio perso con QoS 0 è molto raro, ma impostare a QoS 1 l'iscrizione ai comandi resta un'assicurazione a basso costo.

QoSGaranziaCome funzionaQuando usarla
0Al massimo una voltaIl messaggio parte una sola volta senza conferma; può perdersi se la connessione cade proprio in quel momentoLetture frequenti dei sensori
1Almeno una voltaIl destinatario conferma con PUBACK e, se la conferma non arriva, il messaggio viene reinviato; può arrivare due volteComandi del relè, allarmi
2Esattamente una voltaScambio in quattro passaggi con PUBREC, PUBREL e PUBCOMP; il livello più lentoContatori e casi in cui i duplicati fanno danni; non supportata da PubSubClient

Il flag retain riguarda la memoria più che la consegna: il broker conserva solo l'ultimo messaggio retain di ogni topic e lo invia subito a chiunque si iscriva. È ideale per i messaggi di "stato attuale" come i valori dei sensori, lo stato del relè o la presenza online, ma pericoloso per comandi ed eventi singoli. Le ultime volontà (LWT) lo completano: se il broker non riceve alcun pacchetto dal client per 1,5 volte il periodo di keep-alive, considera persa la connessione e pubblica il messaggio di ultime volontà. Il keep-alive predefinito di PubSubClient è di 15 secondi, quindi un ESP32 scollegato appare "offline" al massimo dopo circa 22 secondi. Puoi cambiarlo con una riga come mqtt.setKeepAlive(30), ma più è lungo, più tardi ti accorgi di una disconnessione.

L'alternativa senza codice: ESPHome

ESPHome è uno strumento gratuito che trasforma un dispositivo descritto in un file YAML in un firmware pronto per l'ESP32; non scrivi neanche una riga di C++. In Home Assistant installa ESPHome Device Builder da Impostazioni > App, apri la sua interfaccia e crea una configurazione con la procedura guidata Nuovo dispositivo. Il primo caricamento si fa una sola volta via USB: Chrome o Edge possono programmare la scheda direttamente e, se non funziona, puoi caricare il file scaricato dalla procedura con la pagina ESPHome Web. Tutti gli aggiornamenti successivi passano via Wi-Fi (OTA). La configurazione qui sotto equivale al progetto Arduino precedente: legge il DHT22 sul GPIO 4 ogni 30 secondi e presenta il relè attivo basso sul GPIO 26 come interruttore. I dati del Wi-Fi e le password vengono letti con !secret da un file secrets.yaml separato:

Codice
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

C'è una differenza da tenere a mente: per impostazione predefinita ESPHome non usa MQTT ma la sua API nativa cifrata. Home Assistant trova il dispositivo da solo in rete e non ha bisogno di alcun broker. Scegli MQTT solo se vuoi che anche altri sistemi come Node-RED leggano gli stessi dati o se non usi Home Assistant. Per farlo, togli il commento alle righe mqtt: in fondo al file ed elimina il blocco api:; se non lo elimini, il dispositivo si riavvia ogni volta che per 15 minuti nessuno si collega all'API nativa (è l'impostazione reboot_timeout). In modalità MQTT, ESPHome invia da solo i messaggi di discovery per Home Assistant e i messaggi online/offline su salon-sensor/status, cioè fa automaticamente tutto ciò che abbiamo fatto a mano nel codice Arduino.

CaratteristicaPubSubClient (codice Arduino)ESPHome (YAML)
ProgrammazioneScrivi tutto tu in C++Solo YAML; il firmware viene compilato automaticamente
Aggiunta a Home AssistantInvii tu i JSON di discoveryRilevato automaticamente
FlessibilitàIllimitata; qualsiasi libreria e logicaLimitata ai componenti già pronti, ma supporta centinaia di sensori; si può aggiungere C++ con le lambda
Aggiornamento wirelessDevi aggiungere tu ArduinoOTAGià incluso
Serve un brokerSìNo con l'API nativa
Valore didatticoInsegna il protocollo MQTT e la programmazioneRisultati rapidi, nasconde cosa succede sotto

MQTT con ESP8266 e Raspberry Pi Pico W

Il codice completo qui sopra funziona senza modifiche sulle schede ESP8266 NodeMCU e Wemos D1 Mini: quando scegli NodeMCU 1.0 in Strumenti > Scheda, il blocco #if defined(ESP8266) seleziona automaticamente ESP8266WiFi.h al posto di WiFi.h e i pin D2 e D1. Sul Raspberry Pi Pico W usiamo invece il modulo MicroPython umqtt.simple. Non è incluso nel firmware MicroPython del Pico W; installalo in Thonny cercando umqtt.simple in Strumenti > Gestisci pacchetti, oppure scrivi import mip; mip.install("umqtt.simple") nella REPL con il Wi-Fi collegato. Il modulo dht che serve per il DHT22, invece, è già nel firmware. Il codice qui sotto fa fare a un Pico W in cucina lo stesso lavoro di misura e di comando del relè. Per tenerlo breve non include i messaggi di discovery; per vedere il Pico W in Home Assistant pubblica gli stessi JSON di discovery del codice ESP32 con i topic ev/mutfak, oppure definisci le entità a mano sotto mqtt: in configuration.yaml. Salva il file come main.py e partirà a ogni accensione della scheda:

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)

Idee di progetti ESP32 MQTT

  • Mappa della temperatura stanza per stanza: Metti in ogni stanza un ESP32 con un DHT22 o un BME280 e segui tutta la casa in un unico grafico con un'iscrizione a ev/+/sicaklik.
  • Lampada e presa smart: Collega il relè a un'automazione di Home Assistant che lo accenda al tramonto e lo spenga a mezzanotte.
  • Sensore per porte e finestre: Con un interruttore reed invia un messaggio MQTT quando la porta si apre e ricevi una notifica sul telefono quando non c'è nessuno in casa.
  • Luce del corridoio a movimento: Lascia che un sensore PIR pubblichi il movimento e che un'automazione di Home Assistant accenda la luce.
  • Stazione di irrigazione: Pubblica il valore del sensore di umidità del terreno e avvia la pompa con un comando MQTT quando la terra è secca.
  • Monitoraggio dei consumi: Misura la corrente di un apparecchio con un sensore di corrente ACS712 e traccia il consumo giornaliero.
  • Sensore a batteria: Costruisci un nodo che misura, invia il dato via MQTT e torna a dormire; i dettagli sono in ESP32 Deep Sleep.

Errori comuni con ESP32 e MQTT e soluzioni

Sintomo o messaggioCausaSoluzione
rc=-2 continuoIP o porta del broker sbagliati, broker spento o Mosquitto in modalità solo localeControlla l'IP, aggiungi listener 1883 alla configurazione, consenti la porta 1883 nel firewall
rc=5Nome utente o password errati, oppure tentativo di connessione senza credenzialiProva la password dal computer con mosquitto_sub; se serve, ricrea l'utente
Si collega, cade dopo pochi secondi e ricominciaDue dispositivi usano lo stesso client ID; Mosquitto scrive nel log "Client esp32-salon already connected, closing old connection."Dai a ogni dispositivo un ISTEMCI_ID univoco
I messaggi di discovery non partono, publish() restituisce falseIl buffer di PubSubClient è di 256 byte per impostazione predefinita e il JSON non ci staChiama mqtt.setBufferSize(1024) in setup()
rc=-3 frequenteUn lungo delay() dentro loop() blocca i keep-alive, oppure il segnale Wi-Fi è deboleGestisci i tempi con millis() e avvicina la scheda al router
I comandi non arrivano all'ESP32Il nome del topic differisce per maiuscole o scrittura, oppure subscribe() non viene ripetuto dopo la riconnessioneVerifica il topic con mosquitto_sub; metti le righe subscribe() dentro la funzione di connessione
Il relè si accende da solo all'avvioSul topic dei comandi c'è un vecchio messaggio retainCancellalo con mosquitto_pub -r -n -t ev/salon/role/komut
Entità "Non disponibile" in Home AssistantIl topic di disponibilità dice offline oppure online è scritto in modo diversoAscolta ev/salon/baglanti e assicurati che il codice pubblichi online dopo la connessione
Caratteri strani al posto del valoreIl payload non termina con \0 ed è stato letto senza usare lengthCopia il payload con un ciclo fino a length
Il dispositivo ESPHome si riavvia ogni 15 minutiIn modalità MQTT c'è ancora il blocco api:, ma Home Assistant non si collega maiElimina il blocco api: o aggiungi reboot_timeout: 0s
Segui un ordine quando cerchi un guasto: prima controlla nel Monitor seriale la connessione Wi-Fi e l'indirizzo IP, poi guarda dal computer con mosquitto_sub -v -t "#" cosa arriva davvero al broker e solo alla fine controlla Home Assistant. Se il messaggio si vede sul broker ma non in Home Assistant, il problema è nel JSON di discovery; se non arriva nemmeno al broker, è sul lato ESP32. Se ti blocchi già sul Wi-Fi, consulta L'ESP32 non si connette al Wi-Fi, e se la scheda si riavvia quando scatta il relè, ESP32 Brownout e Guru Meditation.

Con un broker, qualche topic e PubSubClient, il tuo ESP32 è diventato un dispositivo domotico che parla la stessa lingua del resto della casa. Puoi aggiungere nuovi sensori, altre stanze e schede diverse come il Pico W e gestire tutto da un'unica dashboard di Home Assistant. Nell'app BlueGrays trovi progetti come la connessione Wi-Fi dell'ESP32, la misura di temperatura e umidità con il DHT22, l'illuminazione intelligente con PIR e relè, il controllo in tempo reale con WebSocket e l'irrigazione intelligente delle piante, passo dopo passo con schemi elettrici e codice.

Domande frequenti

Cos'è MQTT e a cosa serve?

MQTT è un protocollo di messaggistica leggero in cui i dispositivi inviano e ricevono messaggi tramite un broker usando nomi di topic. Poiché consuma poca banda e poca energia, è ideale per far inviare dati dei sensori e ricevere comandi a piccoli dispositivi come l'ESP32. Home Assistant, Node-RED e la maggior parte dei sistemi IoT industriali parlano MQTT.

Che porta usa MQTT?

MQTT non cifrato usa per impostazione predefinita la porta 1883, MQTT cifrato con TLS la 8883. La porta WebSocket per le connessioni dal browser dipende dal broker; sul broker Mosquitto di Home Assistant è la 1884. In una rete domestica l'ESP32 di solito si collega alla 1883.

MQTT ha bisogno di internet?

No. Se il broker gira in casa, su un Raspberry Pi o in Home Assistant, il traffico tra ESP32 e broker resta interamente nella rete locale; sensori e relè continuano a funzionare anche se cade internet. Internet serve solo per accedere dall'esterno o per usare un broker nel cloud.

Perché il mio ESP32 non compare in Home Assistant?

Le cause più comuni sono un messaggio di discovery che non entra nel buffer da 256 byte di PubSubClient, un topic config scritto male o un errore di virgolette nel JSON. Ascolta homeassistant/# con mosquitto_sub per verificare che il messaggio arrivi al broker e assicurati che il codice contenga la riga mqtt.setBufferSize(1024). Inoltre l'integrazione MQTT di Home Assistant deve essere collegata allo stesso broker.

Meglio ESPHome o MQTT con Arduino?

Se vuoi ottenere in fretta un dispositivo domotico funzionante, ESPHome richiede meno lavoro: scrivi YAML, il dispositivo compare da solo in Home Assistant e si aggiorna via Wi-Fi. Se vuoi imparare il protocollo MQTT, scrivere la tua logica o lavorare con sistemi diversi da Home Assistant, Arduino con PubSubClient è più flessibile. I due convivono senza problemi nella stessa casa.

Che differenza c'è tra QoS 0, 1 e 2 in MQTT?

La QoS 0 invia il messaggio una volta senza attendere conferma, la QoS 1 lo reinvia finché non viene confermato ma può arrivare due volte, e la QoS 2 garantisce con uno scambio in quattro passaggi che arrivi esattamente una volta. Per le letture dei sensori basta la QoS 0, per i comandi la QoS 1. PubSubClient può pubblicare solo con QoS 0 e iscriversi con QoS 0 o 1.

Vedi tutti i progetti
LED Lampeggiante con ESP32
#103Principiante

LED Lampeggiante con ESP32

Insegna l'uso di base delle uscite GPIO con l'ESP32. Otteniamo un effetto lampeggiante accendendo e spegnendo un LED dal pin digitale. Versione ESP32 del classico progetto blink su Arduino UNO; i comandi di base di blink nell'ambiente Arduino sono gli stessi, ma la disposizione dei pin e i livelli GPIO a 3,3 V dell'ESP32 sono diversi da quelli di Arduino UNO.

4.7(37)
99
Connessione Wi-Fi STA con ESP32 (con display LCD)
#127Avanzato

Connessione Wi-Fi STA con ESP32 (con display LCD)

In questo progetto colleghiamo l'ESP32 alla rete Wi-Fi domestica in modalità Station (STA) in modo sicuro e tollerante agli errori. Separiamo SSID e password in un file secrets.h per impedire fughe su Git, impostiamo un meccanismo di riconnessione automatica e visualizziamo il livello del segnale RSSI e l'indirizzo IP su un display LCD I2C. Il LED interno funge da indicatore di stato.

4.4(21)
34
ESP32 DHT22 Temperatura e umidità (con display LCD)
#117Intermedio

ESP32 DHT22 Temperatura e umidità (con display LCD)

Si tratta di un progetto che misura la temperatura e l'umidità dell'ambiente tramite il sensore DHT22 e le visualizza in tempo reale su un display LCD I2C 16x2. I dati vengono letti dal sensore utilizzando il protocollo one-wire tramite la libreria Adafruit DHT. Questo progetto costituisce la base per stazioni meteorologiche IoT, sistemi di automazione domestica intelligente o sistemi di monitoraggio ambientale nelle serre. La comunicazione con il DHT22 avviene tramite il pin GPIO 4 dell'ESP32.

4.8(38)
56
Illuminazione Intelligente ESP32 (PIR + LDR + Relè + OLED)
#141Avanzato
Premium

Illuminazione Intelligente ESP32 (PIR + LDR + Relè + OLED)

Trasforma il tuo corridoio, bagno o dispensa in illuminazione intelligente con ESP32! Utilizzando un sensore di movimento PIR, un sensore di luce LDR e un modulo relè, costruiamo lo scenario classico "la luce si accende quando viene rilevato movimento al buio" — se l'ambiente è già luminoso, il movimento NON attiva la luce, risparmiando energia durante il giorno. La luce rimane accesa per 30 secondi; se il movimento continua, il timer si azzera e la luce rimane accesa più a lungo. Il display OLE

4.3(6)
11
Contatore WebSocket ESP32 (2 pulsanti + LCD + Web in tempo reale)
#130Avanzato
Premium

Contatore WebSocket ESP32 (2 pulsanti + LCD + Web in tempo reale)

In questo progetto due pulsanti collegati all'ESP32 (GPIO 5 incrementa, GPIO 4 decrementa) modificano un contatore. Il valore si aggiorna all'istante su un display LCD I2C 16x2 e, grazie al supporto WebSocket di ESPAsyncWebServer, in tutti i browser collegati senza ricaricare la pagina. Al posto del polling HTTP si usa un'unica connessione persistente e l'ESP32 invia il nuovo valore a tutti con ws.textAll().

4.5(14)
23
ESP32 mDNS: accesso al dispositivo tramite bluegrays-esp.local (con schermo LCD)
#131Avanzato
Premium

ESP32 mDNS: accesso al dispositivo tramite bluegrays-esp.local (con schermo LCD)

In questo progetto, aggiungendo il servizio mDNS (Multicast DNS) all'ESP32, consentiamo l'accesso tramite un nome host leggibile, come bluegrays-esp.local, anziché tramite l'indirizzo IP. Anche se l'IP assegnato dal DHCP dovesse cambiare, potrete sempre raggiungere il dispositivo con lo stesso nome. Eseguendo anche un piccolo server web, inviamo comandi di controllo dei LED dal browser all’indirizzo http://bluegrays-esp.local/. Sul display LCD I2C vengono visualizzati il nome host, l’IP e lo

4.8(14)
23
Sistema di Allarme Movimento ESP32 (PIR + Buzzer + LED + Telegram)
#145Avanzato
Premium

Sistema di Allarme Movimento ESP32 (PIR + Buzzer + LED + Telegram)

Un sistema di allarme di sicurezza intelligente che attiva buzzer e LED quando il sensore PIR rileva movimento, inviando contemporaneamente una notifica istantanea al proprietario tramite Telegram. Dispone di un tempo di attesa di 30 secondi per limitare la frequenza degli allarmi ripetuti; questo meccanismo non verifica la validità dei rilevamenti del sensore PIR né elimina le false attivazioni. Adatto a sicurezza domestica, monitoraggio di garage, magazzini o studi. Con l'ESP32-CAM è possibile

0.0(0)
9