Rehberler · 13 dk okuma

ESP32 MQTT Rehberi: Mosquitto, Home Assistant ve ESPHome

ESP32 MQTT rehberi: Mosquitto kurulumu, PubSubClient ile sensör yayınlama ve röle kontrolü, Home Assistant keşfi, ESPHome YAML örneği, QoS ve sık hatalar.

ESP32 MQTT ikilisi, evdeki sensörlerin ve rölelerin birbirleriyle ve Home Assistant gibi bir akıllı ev sistemiyle konuşmasının en yaygın yoludur. MQTT, küçük cihazlar için tasarlanmış hafif bir mesajlaşma protokolüdür: ESP32 ölçtüğü sıcaklığı "ev/salon/sicaklik" gibi bir konuya (topic) bırakır, o konuyu dinleyen her program değeri anında alır. Aynı yoldan, telefondaki Home Assistant uygulamasında bir düğmeye bastığında giden "ON" komutu saniyenin altında ESP32'ye ulaşır ve röleyi çeker. HTTP'deki gibi her istek için yeni bağlantı kurulmaz; tek bir açık bağlantı üzerinden, en az iki baytlık başlıklarla çalıştığı için hem hızlıdır hem de Wi-Fi'ı ve işlemciyi yormaz.

Bu rehberde sıfırdan çalışan bir akıllı ev düğümü kuracaksın. Önce MQTT'nin broker, topic, publish ve subscribe kavramlarını öğrenecek, ardından Home Assistant'ta ya da bir Raspberry Pi'de Mosquitto broker'ını kuracaksın. Sonra PubSubClient kütüphanesiyle ESP32'den DHT22 sıcaklık ve nem değerlerini yayınlayacak, röle komutlarını dinleyecek ve cihazın Home Assistant'ta kendiliğinden görünmesini sağlayan MQTT Discovery'yi ekleyeceksin. QoS ve retain ayarlarını, bağlantı koptuğunda cihazı "kullanılamıyor" gösteren son vasiyet (LWT) mesajını, hiç C++ yazmadan aynı işi yapan ESPHome alternatifini, ESP8266 ve Raspberry Pi Pico W farklarını ve en sık karşılaşılan hataları da tek tek ele alacağız.

MQTT ile Home Assistant'a bağlanan ESP32 geliştirme kartı
ESP32, dahili Wi-Fi'ı sayesinde ev ağındaki MQTT broker'ına doğrudan bağlanır; sensör verisi ve röle komutları aynı bağlantı üzerinden akar.

MQTT nedir, nasıl çalışır?

MQTT (Message Queuing Telemetry Transport), yayınla-abone ol (publish/subscribe) modeliyle çalışır. Ortada broker adı verilen bir sunucu bulunur; ESP32, Home Assistant, telefonun ya da bilgisayarındaki bir program bu sunucuya istemci olarak bağlanır. İstemciler birbirini tanımaz, IP adreslerini bilmez: biri bir konuya mesaj yayınlar, broker bu mesajı o konuya abone olan herkese iletir. Bunu bir postane gibi düşünebilirsin: ESP32 mektubu "ev/salon/sicaklik" adresli kutuya atar, o kutuyu takip eden Home Assistant mektubu anında alır. Bağlantıyı her zaman istemci başlattığı için ESP32'nin sabit IP'ye ya da modemde açılmış bir porta ihtiyacı yoktur; tek bilmesi gereken broker'ın adresidir.

KavramNe işe yarar?Örnek
BrokerMesajları alan ve abonelere dağıtan sunucuMosquitto, Home Assistant'taki Mosquitto broker
İstemci (client)Broker'a bağlanan her cihaz ya da program; benzersiz bir kimliği (client ID) olurESP32, Home Assistant, MQTT Explorer
Topic (konu)Mesajın adresi; eğik çizgiyle ayrılmış seviyelerden oluşurev/salon/sicaklik
Publish (yayınla)Bir konuya mesaj göndermek"23.4" değerini ev/salon/sicaklik konusuna yollamak
Subscribe (abone ol)Bir konudaki mesajları almak için kaydolmakESP32'nin ev/salon/role/komut konusunu dinlemesi
Payload (yük)Mesajın içeriği; metin, sayı ya da JSON olabilirON, 23.4, {"sicaklik":23.4}
RetainBroker'ın konudaki son mesajı saklayıp yeni abonelere hemen vermesiRöle durumu: ON
LWT (son vasiyet)İstemci habersizce koparsa broker'ın onun adına yayınladığı mesajev/salon/baglanti: offline
QoSMesajın teslim garantisi seviyesi (0, 1 ya da 2)Röle komutları için QoS 1

Neden MQTT? Web sunucusu, Blynk ve Telegram ile karşılaştırma

YöntemArtısıEksisiEn uygun olduğu iş
MQTT + Home AssistantYerel ve hızlı, çift yönlü; yüzlerce cihaz tek panelde, otomasyon kurulabilirBir broker kurmak gerekirBütün evi tek merkezden yönetmek
ESP32 web sunucusuEk sunucu gerekmez, tarayıcıdan açılırHer cihazın ayrı sayfası olur, cihazlar arası otomasyon yokturTek cihazlık kontrol paneli
Blynk IoTHazır telefon paneli, internetten erişimBuluta bağımlı, ücretsiz planda sınırlar varHızlı mobil prototip
Telegram botuÜcretsiz anlık bildirim, port açmak gerekmezGrafik ve panel yokturAlarm ve basit komutlar
ESP-NOWModem ve broker olmadan ESP'ler arasında haberleşmeYalnız ESP kartları arasında, Home Assistant'a doğrudan ulaşmazPille çalışan sensörden ağ geçidine veri taşımak

Kısacası MQTT, cihaz sayısı arttıkça parlayan yöntemdir: yeni bir sensör eklediğinde mevcut kodların hiçbirine dokunmazsın, sadece yeni bir konu yayınlamaya başlarsın. Tek bir cihazı tarayıcıdan yönetmek istiyorsan ESP32 Async Web Server ve WebSocket, telefona bildirim istiyorsan ESP32 Telegram Bot, hazır bir mobil panel istiyorsan Blynk ESP32 rehberleri daha kısa yoldan sonuç verir. Modemin ulaşamadığı bir bahçe sensörü içinse ESP-NOW ile veriyi MQTT'ye bağlı bir ağ geçidi ESP32'ye taşımak iyi bir çözümdür.

MQTT topic yapısı ve joker karakterler

Topic'ler bir klasör yoluna benzer: "ev/salon/sicaklik" üç seviyeden oluşur ve büyük-küçük harfe duyarlıdır, yani "Ev/Salon" ile "ev/salon" iki ayrı konudur. Başa eğik çizgi koyma ("/ev/salon" boş bir ilk seviye üretir), boşluk ve Türkçe karakter kullanma; İngilizce harfler, rakamlar, tire ve alt çizgi yeterlidir. Abone olurken iki joker karakter kullanabilirsin: + tek bir seviyenin yerini tutar ("ev/+/sicaklik" bütün odaların sıcaklığını getirir), # ise kendisinden sonraki her şeyi kapsar ve yalnızca en sonda yazılır ("ev/#" evdeki bütün mesajları getirir). Jokerler yalnızca abone olurken geçerlidir; bir mesaj her zaman tam bir konuya yayınlanır. $ ile başlayan konular ($SYS gibi) broker'ın kendi istatistiklerine ayrılmıştır ve # aboneliğine dahil edilmez. Bu rehberdeki proje için şu düzeni kullanacağız:

TopicYayınlayanDinleyenRetain
ev/salon/sicaklikESP32 (30 saniyede bir)Home AssistantEvet
ev/salon/nemESP32 (30 saniyede bir)Home AssistantEvet
ev/salon/role/komutHome Assistant, telefon, otomasyonlarESP32Hayır
ev/salon/role/durumESP32 (her değişimde)Home AssistantEvet
ev/salon/baglantiESP32 (online), broker (offline)Home AssistantEvet
homeassistant/statusHome Assistant (açılışta online)ESP32Hayır

MQTT broker kurulumu: Mosquitto

En yaygın ve ücretsiz MQTT broker'ı Eclipse Mosquitto'dur; bir Raspberry Pi'de bile saniyede yüzlerce mesajı rahatça taşır. Kurmanın üç kolay yolu var: Home Assistant OS kullanıyorsan resmi Mosquitto broker uygulaması, ayrı bir Raspberry Pi ya da Linux bilgisayar kullanıyorsan apt paketi, Windows'ta ise Mosquitto'nun kurulum dosyası. Hangisini seçersen seç, broker şifresiz MQTT için 1883, TLS ile şifrelenmiş MQTT için 8883 portunu kullanır ve ESP32 ile aynı ev ağında olması yeterlidir. Home Assistant'ta kurulum şöyle:

  1. Home Assistant'ta Ayarlar > Uygulamalar bölümünü aç (eski sürümlerde bu bölümün adı Eklentiler / Add-ons'tur), Uygulama yükle düğmesine bas ve listeden Mosquitto broker'ı seç.
  2. Yükle düğmesine bas; kurulum bitince Başlat'a bas ve açılışta başlatma seçeneğini açık bırak.
  3. ESP32 için ayrı bir kullanıcı aç: Ayarlar > Kişiler > Kullanıcılar bölümünden "esp32" adında bir kullanıcı ve güçlü bir şifre oluştur. Bu sekmeyi göremiyorsan profil sayfanda Gelişmiş modu aç. "homeassistant" ve "addons" adları broker için ayrılmıştır, bunları kullanma.
  4. Ayarlar > Cihazlar ve hizmetler sayfasında MQTT entegrasyonu genellikle "Bulundu" olarak kendiliğinden çıkar; Yapılandır'a basıp onayla. Çıkmazsa Entegrasyon ekle düğmesiyle MQTT'yi arat ve Mosquitto'yu otomatik yapılandırma seçeneğini kullan.
  5. ESP32 kodunda broker adresi olarak Home Assistant'ın IP adresini (örneğin 192.168.1.10), port olarak 1883'ü ve az önce açtığın kullanıcıyı yazacaksın.

Raspberry Pi ya da Ubuntu gibi bir Linux makinede kurulum birkaç komuttur. sudo apt install mosquitto mosquitto-clients ile broker'ı ve test araçlarını kur. sudo mosquitto_passwd -c /etc/mosquitto/passwd esp32 komutuyla "esp32" kullanıcısını oluştur ve şifreyi iki kez gir; -c parametresi dosyayı sıfırdan yaratır, bu yüzden ikinci kullanıcıyı eklerken -c yazma, yoksa önceki kullanıcılar silinir. Sonra /etc/mosquitto/conf.d/ klasöründe yerel.conf adında bir dosya oluşturup aşağıdaki üç satırı yaz ve sudo systemctl restart mosquitto ile servisi yeniden başlat. Windows'ta aynı satırları Mosquitto'nun kurulum klasöründeki mosquitto.conf dosyasına ekleyip Mosquitto Broker servisini yeniden başlatman yeterlidir.

SatırAnlamı
listener 1883Bütün ağ arayüzlerinde 1883 portunu dinler; bu satır olmadan Mosquitto 2.x yalnızca aynı bilgisayardan gelen bağlantıları kabul eder
allow_anonymous falseKullanıcı adı ve şifresi olmayan bağlantıları reddeder; 2.x sürümlerinde zaten varsayılandır ama açıkça yazmak iyi bir alışkanlıktır
password_file /etc/mosquitto/passwdmosquitto_passwd ile oluşturduğun şifre dosyasını kullanır; şifreler dosyada özetlenmiş (hash) olarak saklanır
Mosquitto 2.0 ve sonrası, yapılandırmada bir listener tanımlanmamışsa yalnızca 127.0.0.1 adresini dinler ve günlüğe "Starting in local only mode. Connections will only be possible from clients running on this machine." uyarısını yazar. Bu durumda ESP32 bağlanamaz ve rc=-2 hatası alırsın. Öte yandan 1883 portunu modeminden internete açma (port yönlendirme yapma): şifresiz MQTT trafiği yolda okunabilir ve evdeki röleler başkalarının eline geçebilir. Evin dışından erişmen gerekiyorsa bir VPN ya da Home Assistant'ın uzaktan erişim çözümlerini kullan.

ESP32'ye geçmeden önce broker'ı bilgisayarından test et; sorunun kodda mı broker'da mı olduğunu baştan ayırmak sana çok zaman kazandırır. Bir terminalde mosquitto_sub -h 192.168.1.10 -u esp32 -P sifren -t "ev/#" -v komutuyla evdeki bütün konuları dinlemeye başla. İkinci bir terminalde mosquitto_pub -h 192.168.1.10 -u esp32 -P sifren -t ev/salon/test -m merhaba yaz. İlk terminalde "ev/salon/test merhaba" satırı görünüyorsa broker çalışıyor ve şifre doğru demektir. -v parametresi her mesajın önüne konusunu yazar, -r parametresi ise mesajı retain olarak gönderir.

Komut satırı sevmiyorsan ücretsiz MQTT Explorer programı broker'daki bütün konuları ağaç görünümünde, son değerleri ve retain işaretleriyle birlikte gösterir. Home Assistant içinde de Ayarlar > Cihazlar ve hizmetler > MQTT > Yapılandır sayfasındaki "Bir konuyu dinle" kutusuna ev/# yazıp dinlemeye başlayabilir, "Paket yayınla" bölümünden de ESP32'ye elle komut gönderebilirsin.

Gerekli malzemeler ve bağlantı şeması

Proje için bir ESP32 geliştirme kartı, bir DHT22 sıcaklık ve nem sensörü, 3,3 V ile tetiklenebilen bir röle modülü, breadboard ve jumper kablolar yeterli. DHT22, DHT11'e göre daha hassastır: sıcaklığı ±0,5 °C, nemi yaklaşık ±%2–5 doğrulukla ölçer ve -40 ile 80 °C arasında çalışır; sensör ailesini DHT11 Sıcaklık ve Nem Sensörü yazısında ayrıntılı anlattık. Elinde DHT11 varsa koddaki DHT22 yazan yeri DHT11 yapman yeterli. İlk bağlantı testi için yalnızca ESP32 ve bir USB kablosu yeter; sensörü ve röleyi sonra ekleyebilirsin.

ESP32
ESP32
DHT22
DHT22
Röle / Relay
Röle / Relay
BağlantıESP32ESP8266 (NodeMCU)Raspberry Pi Pico W
DHT22 VCC3V33V33V3(OUT)
DHT22 DATAGPIO 4D2 (GPIO 4)GP15
DHT22 GNDGNDGNDGND
Röle VCCVIN (5V)VIN (5V)VBUS (5V)
Röle INGPIO 26D1 (GPIO 5)GP14
Röle GNDGNDGNDGND
ESP32, ESP8266 ve Pico'nun pinleri 3,3 V ile çalışır ve 5 V'a dayanıklı değildir; DHT22'yi bu yüzden 3V3 pininden besliyoruz. Üç pinli DHT22 modüllerinin üzerinde genellikle çekme (pull-up) direnci bulunur; dört bacaklı çıplak sensör kullanıyorsan DATA ile VCC arasına 4,7–10 kΩ bir direnç ekle. Röleyle 220 V şebeke yükü anahtarlayacaksan bağlantıları fiş çekiliyken yap ve bir yetişkinden yardım al; ayrıntılar Röle Modülü Nedir? yazısında. Kartın bütün pinlerini Pinout aracında görebilirsin.

Arduino IDE'de PubSubClient kurulumu

  1. Arduino IDE'de ESP32 kart paketi kurulu değilse önce onu kur; adımlar ESP32 Nedir? yazısında.
  2. Araçlar > Kütüphaneleri Yönet menüsünü aç, arama kutusuna PubSubClient yaz ve yazarı Nick O'Leary olan kütüphaneyi kur. Bu rehberdeki kodlar 2.8 sürümüyle derlendi.
  3. Aynı pencerede DHT sensor library ara ve Adafruit'in kütüphanesini kur; bağımlılıkları sorduğunda Install all seçerek Adafruit Unified Sensor'ı da kur.
  4. Kütüphane kurarken sorun yaşarsan Arduino Kütüphane Ekleme rehberine göz at.

İlk test: ESP32'yi MQTT broker'a bağlamak

Sensörlere geçmeden önce Wi-Fi, broker adresi ve şifrenin doğru olduğunu en basit kodla doğrulayalım. Aşağıdaki kod broker'a bağlanır, "test/esp32/durum" konusuna "merhaba" yayınlar ve "test/esp32/komut" konusuna gelen her mesajı Seri Monitör'e yazar. Wi-Fi adını, şifreni, broker IP'sini ve MQTT kullanıcısını kendi bilgilerinle değiştir, kodu yükle ve Seri Monitör'ü 115200 baud hızında aç:

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}

Seri Monitör'de "baglandi" yazısını gördükten sonra bilgisayarındaki terminalden mosquitto_pub -h 192.168.1.10 -u esp32 -P sifren -t test/esp32/komut -m selam gönder; birkaç milisaniye içinde Seri Monitör'de "Mesaj [test/esp32/komut] selam" satırı belirir. Bağlantı başarısız olursa kod mqtt.state() ile bir hata kodu yazar ve 5 saniye sonra yeniden dener. Bu kodlar sorunun nerede olduğunu doğrudan söyler:

rcPubSubClient adıAnlamı ve çözümü
-4MQTT_CONNECTION_TIMEOUTBroker zamanında yanıt vermedi; ağ zayıf ya da broker aşırı yüklü
-3MQTT_CONNECTION_LOSTKurulu bağlantı koptu; çoğunlukla loop() uzun süre çağrılmadığı ya da Wi-Fi gittiği için
-2MQTT_CONNECT_FAILEDTCP bağlantısı hiç kurulamadı: IP ya da port yanlış, broker kapalı, Mosquitto yalnız yerel modda ya da güvenlik duvarı 1883'ü engelliyor
-1MQTT_DISCONNECTEDBağlantı düzgün şekilde kapatıldı (disconnect çağrıldı) ya da henüz hiç bağlanılmadı
2MQTT_CONNECT_BAD_CLIENT_IDİstemci kimliği reddedildi; boş ya da geçersiz bir client ID kullanılmış
4MQTT_CONNECT_BAD_CREDENTIALSKullanıcı adı ya da şifre hatalı (bazı broker'lar bu kodu döndürür)
5MQTT_CONNECT_UNAUTHORIZEDYetki yok; Mosquitto hem yanlış şifrede hem de şifresiz bağlanmaya çalışıldığında bu kodu döndürür

ESP32 ile sensör verisi yayınlama ve röle komutu dinleme

Şimdi asıl projeyi kuruyoruz. Aşağıdaki kod 30 saniyede bir DHT22'yi okuyup sıcaklığı ve nemi retain bayrağıyla yayınlar, "ev/salon/role/komut" konusuna gelen ON, OFF ve TOGGLE komutlarıyla röleyi yönetir ve rölenin yeni durumunu "ev/salon/role/durum" konusuna bildirir. Bağlanırken broker'a bir son vasiyet bırakır, Home Assistant'a kendini MQTT Discovery ile tanıtır ve bağlantı koptuğunda loop()'u kilitlemeden 5 saniyede bir yeniden bağlanmayı dener. Kodun başındaki #if defined(ESP8266) bloğu sayesinde aynı kod hiçbir değişiklik yapmadan NodeMCU'da da derlenir.

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}
SatırGörevi
mqtt.connect(ISTEMCI_ID, ..., T_BAGLANTI, 1, true, "offline")Bağlanırken son vasiyeti de bildirir: ESP32 habersizce koparsa broker ev/salon/baglanti konusuna kalıcı olarak "offline" yazar
mqtt.publish(T_BAGLANTI, "online", true)Bağlanır bağlanmaz durumu "online" yapar; Home Assistant cihazı yeniden kullanılabilir gösterir
mqtt.subscribe(T_KOMUT, 1)Röle komutlarını QoS 1 ile dinler; PubSubClient abonelikte yalnızca QoS 0 ve 1'i destekler
mqtt.setBufferSize(1024)Paket tamponunu varsayılan 256 bayttan büyütür; en büyük keşif paketi yaklaşık 355 bayttır
mqtt.loop()Gelen mesajları okur ve keep-alive (PINGREQ) paketlerini gönderir; her loop turunda çağrılmalıdır
ROLE_AKTIF_LOWÇoğu röle modülü LOW sinyalle çeker; modülün HIGH ile çekiyorsa false yap
OLCUM_ARALIGIÖlçüm sıklığı; DHT22 en fazla 2 saniyede bir okunabilir, oda sıcaklığı için 30–60 saniye idealdir

Koddaki birkaç ayrıntı bilerek seçildi. mesajGeldi() fonksiyonu konu ve payload'ı ilk iş olarak String'e kopyalar, çünkü PubSubClient gelen ve giden mesajlar için tek bir tampon kullanır: geri çağırma içinde publish() yaptığın anda topic ve payload işaretçilerinin gösterdiği veri silinir. Payload'ın sonunda C dizilerindeki gibi \0 karakteri de yoktur; bu yüzden length değeri kadar karakter okuyoruz. Ölçümlerde ve röle durumunda retain kullanıyoruz ki Home Assistant yeniden başladığında son değeri 30 saniye beklemeden görsün. Zamanlama da millis() ile yapılıyor: loop() içinde uzun bir delay() olsaydı keep-alive paketleri gecikir, broker bağlantıyı düşürürdü. Bu tekniği Arduino millis() ve delay() Farkı yazısında ayrıntılı anlattık.

Komut konularına asla retain bayrağıyla mesaj gönderme. "ev/salon/role/komut" konusunda retain'li bir "ON" kalırsa ESP32 elektrik kesintisinden ya da Wi-Fi kopmasından sonra her yeniden bağlandığında bu eski komutu tekrar alır ve röleyi gecenin bir yarısı kendiliğinden açar. Yanlışlıkla retain'li komut gönderdiysen mosquitto_pub -r -n -t ev/salon/role/komut komutuyla boş bir retain mesajı yayınlayarak onu silebilirsin. Home Assistant'ın MQTT anahtarları komutları varsayılan olarak retain'siz gönderir.

Home Assistant'ta görünüm: MQTT Discovery

Home Assistant, homeassistant/ önekiyle başlayan konuları sürekli dinler. Bir cihaz homeassistant/[tür]/[düğüm]/[nesne]/config biçimindeki bir konuya JSON yapılandırması yayınladığında Home Assistant o varlığı kendiliğinden oluşturur; buna MQTT Discovery denir. Bizim kodumuz üç mesaj gönderir: iki sensör (sıcaklık ve nem) için homeassistant/sensor/esp32-salon/... ve röle için homeassistant/switch/esp32-salon/role/config. Mesajlar retain'li olduğu için Home Assistant yeniden başladığında bile kaybolmaz. Ayrıca kod homeassistant/status konusuna abonedir: Home Assistant açıldığında buraya "online" yazar ve ESP32 tanıtımı yeniler. Home Assistant'ın belgeleri, çok sayıda cihaz varsa bu yeniden tanıtımın küçük rastgele bir gecikmeyle yapılmasını önerir.

JSON alanıAnlamıBizim değerimiz
nameVarlığın görünen adı; başına cihaz adı eklenirSıcaklık (Salon ESP32 Sıcaklık olarak görünür)
unique_idVarlığın değişmeyen kimliği; olmazsa varlığın adı ve odası arayüzden düzenlenemezesp32-salon_sicaklik
state_topicDeğerin okunacağı konuev/salon/sicaklik
command_topicAnahtar (switch) komutlarının gönderileceği konuev/salon/role/komut
device_classSimgeyi, birim seçeneklerini ve grafik türünü belirlertemperature, humidity
unit_of_measurementÖlçü birimi°C ve %
state_classmeasurement değeri uzun dönem istatistik ve grafik tutulmasını sağlarmeasurement
availability_topiconline/offline durumunun okunacağı konu; varsayılan yükler online ve offline'dırev/salon/baglanti
deviceVarlıkları tek bir cihaz kartında toplaridentifiers, name, model

Kodu yükledikten birkaç saniye sonra Ayarlar > Cihazlar ve hizmetler > MQTT sayfasında "Salon ESP32" adlı bir cihaz belirir. Cihaz kartında sıcaklık ve nem sensörleri ile bir röle anahtarı bulunur; sıcaklığa tıkladığında geçmiş grafiği açılır, anahtara bastığında röle çeker. Bu varlıkları panoya (dashboard) ekleyebilir, sesli asistanlara açabilir ya da otomasyonlarda kullanabilirsin: örneğin "salon sıcaklığı 27 °C'yi geçerse vantilatörün bağlı olduğu röleyi aç, 25 °C'nin altına inince kapat" kuralı birkaç tıklamayla kurulur. ESP32'nin fişini çektiğinde en geç 22 saniye kadar sonra varlıklar "Kullanılamıyor" durumuna geçer; bu, son vasiyet mesajının çalıştığını gösterir. Discovery kullanmak istemezsen aynı varlıkları configuration.yaml dosyasında mqtt: başlığı altına sensor ve switch olarak elle de tanımlayabilirsin.

Cihazın adını ya da konularını değiştirdin ve Home Assistant'ta eski varlıklar kaldıysa, ilgili config konusuna boş bir retain mesajı gönder: mosquitto_pub -r -n -t homeassistant/sensor/esp32-salon/sicaklik/config. Home Assistant varlığı siler, cihaza bağlı başka varlık kalmadıysa cihazı da kaldırır. Her ESP32'ye farklı bir ISTEMCI_ID verdiğinde unique_id'ler de kendiliğinden farklı olur ve birden fazla odayı karışıklık olmadan ekleyebilirsin.

QoS ve retain: hangisi ne zaman kullanılır?

QoS (Quality of Service), bir mesajın karşı tarafa ulaştığından ne kadar emin olmak istediğini belirler. Önemli bir ayrıntı: QoS iki ayrı yolda ayrı ayrı uygulanır. Yayınlayan ile broker arasında yayınlayanın seçtiği QoS, broker ile abone arasında ise aboneliğin QoS'u geçerlidir; abonenin aldığı mesajın garantisi bu ikisinden düşük olanıdır. PubSubClient yayınlarda yalnızca QoS 0'ı, aboneliklerde QoS 0 ve 1'i destekler. Ev içi Wi-Fi'da QoS 0 ile kaybolan mesaj çok nadirdir; yine de komutlar için aboneliği QoS 1 yapmak ucuz bir sigortadır.

QoSGarantiNasıl çalışır?Ne zaman kullanılır?
0En fazla bir kezMesaj tek sefer gönderilir, onay beklenmez; bağlantı o an koparsa kaybolabilirSık gelen sensör ölçümleri
1En az bir kezAlıcı PUBACK ile onaylar, onay gelmezse mesaj yeniden gönderilir; aynı mesaj iki kez gelebilirRöle komutları, alarmlar
2Tam olarak bir kezPUBREC, PUBREL ve PUBCOMP ile dört adımlı el sıkışma; en yavaş seviyeTekrarın zararlı olduğu sayaç gibi işler; PubSubClient desteklemez

Retain bayrağı ise teslimle değil hafızayla ilgilidir: broker her konunun yalnızca son retain'li mesajını saklar ve o konuya yeni abone olan herkese hemen gönderir. Sensör değerleri, röle durumu ve çevrimiçi bilgisi gibi "şu anki durum" mesajları için idealdir; komutlar ve tek seferlik olaylar için ise tehlikelidir. Son vasiyet (LWT) bunun tamamlayıcısıdır: broker, istemciden keep-alive süresinin 1,5 katı boyunca hiçbir paket gelmezse bağlantının koptuğuna karar verir ve vasiyet mesajını yayınlar. PubSubClient'ın varsayılan keep-alive süresi 15 saniyedir, yani fişi çekilen bir ESP32 en geç yaklaşık 22 saniye sonra "offline" görünür. Bu süreyi mqtt.setKeepAlive(30) gibi bir satırla değiştirebilirsin, ama uzattıkça kopmayı daha geç fark edersin.

ESPHome ile kodsuz alternatif

ESPHome, YAML dosyasıyla tarif ettiğin cihazı ESP32 için hazır bir yazılıma dönüştüren ücretsiz bir araçtır; tek satır C++ yazmazsın. Home Assistant'ta Ayarlar > Uygulamalar bölümünden ESPHome Device Builder'ı kur, arayüzünü aç ve Yeni cihaz sihirbazıyla bir yapılandırma oluştur. İlk yükleme bir kez USB kablosuyla yapılır: Chrome ya da Edge tarayıcısı kartı doğrudan programlayabilir, olmazsa sihirbazın indirdiği dosyayı ESPHome Web sayfasıyla yükleyebilirsin. Sonraki bütün güncellemeler Wi-Fi üzerinden kablosuz (OTA) gider. Aşağıdaki yapılandırma, yukarıdaki Arduino projesinin aynısıdır: GPIO 4'teki DHT22'yi 30 saniyede bir okur ve GPIO 26'daki aktif LOW röleyi bir anahtar olarak sunar. Wi-Fi ve şifre bilgileri !secret ile ayrı secrets.yaml dosyasından okunur:

Kod
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

Dikkat etmen gereken bir fark var: ESPHome varsayılan olarak MQTT değil, kendi şifreli native API'sini kullanır. Home Assistant cihazı ağda kendiliğinden bulur ve broker'a hiç ihtiyaç duymaz. MQTT'yi ancak Node-RED gibi başka sistemlerin de aynı veriyi okumasını istiyorsan ya da Home Assistant kullanmıyorsan seçmelisin. Bunun için dosyanın sonundaki mqtt: satırlarını aç ve api: bloğunu sil; silmezsen cihaz 15 dakika boyunca native API'ye kimse bağlanmadığında kendini yeniden başlatır (bu süre reboot_timeout ayarıdır). MQTT modunda ESPHome, Home Assistant keşif mesajlarını ve salon-sensor/status konusundaki online/offline mesajlarını kendisi gönderir; yani bizim Arduino kodunda elle yaptığımız her şeyi otomatik yapar.

ÖzellikPubSubClient (Arduino kodu)ESPHome (YAML)
Kod yazmaHer şeyi C++ ile sen yazarsınYalnızca YAML; yazılım otomatik derlenir
Home Assistant'a eklemeKeşif JSON'larını sen gönderirsinKendiliğinden bulunur
EsneklikSınırsız; her kütüphane ve mantık kullanılabilirHazır bileşenlerle sınırlı ama yüzlerce sensör destekli; gerekirse lambda ile C++ eklenir
Kablosuz güncellemeArduinoOTA'yı koda sen eklersinHazır gelir
Broker gereksinimiGerekliNative API ile gerekmez
Öğrenme değeriMQTT protokolünü ve programlamayı öğretirHızlı sonuç verir, arka planı gizler

ESP8266 ve Raspberry Pi Pico W ile MQTT

Yukarıdaki tam kod ESP8266 NodeMCU ve Wemos D1 Mini kartlarında olduğu gibi çalışır: Araçlar > Kart menüsünden NodeMCU 1.0 seçtiğinde #if defined(ESP8266) bloğu WiFi.h yerine ESP8266WiFi.h dosyasını ve D2, D1 pinlerini kendiliğinden seçer. Raspberry Pi Pico W tarafında ise MicroPython'un umqtt.simple modülünü kullanırız. Bu modül Pico W'nun MicroPython yazılımında hazır gelmez; Thonny'de Araçlar > Paketleri Yönet menüsünden umqtt.simple aratarak ya da Wi-Fi'ya bağlıyken komut satırında import mip; mip.install("umqtt.simple") yazarak kurabilirsin. DHT22 için gereken dht modülü ise yazılımla birlikte gelir. Aşağıdaki kod mutfağa koyduğun bir Pico W'nun aynı ölçüm ve röle işini yapmasını sağlar. Kod kısa kalsın diye keşif mesajlarını eklemedik; Pico W'yu Home Assistant'ta görmek için ESP32 kodundaki keşif JSON'larını ev/mutfak konularıyla yayınlayabilir ya da varlıkları configuration.yaml dosyasında mqtt: başlığı altında elle tanımlayabilirsin. Dosyayı main.py adıyla kaydedersen kart her açıldığında çalışır:

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)

ESP32 MQTT proje fikirleri

  • Oda oda sıcaklık haritası: Her odaya bir ESP32 ile DHT22 ya da BME280 koy, ev/+/sicaklik aboneliğiyle bütün evi tek grafikte izle.
  • Akıllı lamba ve priz: Röleyi Home Assistant otomasyonuna bağla; gün batımında yakıp gece yarısı söndür.
  • Kapı ve pencere sensörü: Bir reed röle ile kapı açılınca MQTT'ye mesaj gönder, evde kimse yokken telefona bildirim al.
  • Hareketle yanan koridor ışığı: PIR sensörü hareketi yayınlasın, ışığı Home Assistant otomasyonu yaksın.
  • Bitki sulama istasyonu: Toprak nem sensörü değerini yayınla, nem düşünce pompayı MQTT komutuyla çalıştır.
  • Enerji izleme: ACS712 akım sensörü ile bir cihazın çektiği akımı ölç ve günlük tüketimi grafikle.
  • Pille çalışan sensör: Ölçüm yapıp MQTT'ye gönderen, sonra uykuya dalan bir düğüm kur; ayrıntılar ESP32 Deep Sleep yazısında.

ESP32 MQTT sık hataları ve çözümleri

Belirti ya da mesajSebepÇözüm
Sürekli rc=-2Broker IP'si ya da portu yanlış, broker kapalı ya da Mosquitto yalnız yerel moddaIP'yi kontrol et, yapılandırmaya listener 1883 ekle, güvenlik duvarında 1883 portuna izin ver
rc=5Kullanıcı adı ya da şifre yanlış, ya da şifresiz bağlanılmaya çalışılıyorŞifreyi mosquitto_sub ile bilgisayardan dene; gerekirse kullanıcıyı yeniden oluştur
Bağlanıyor, birkaç saniyede kopuyor, döngü sürüyorİki cihaz aynı client ID'yi kullanıyor; Mosquitto günlüğe "Client esp32-salon already connected, closing old connection." yazarHer cihaza benzersiz bir ISTEMCI_ID ver
Keşif mesajları gitmiyor, publish() false döndürüyorPubSubClient tamponu varsayılan 256 bayt, JSON sığmıyorsetup() içinde mqtt.setBufferSize(1024) çağır
Sık sık rc=-3loop() içinde uzun delay() var, keep-alive gönderilemiyor ya da Wi-Fi sinyali zayıfZamanlamayı millis() ile yap, kartı modeme yaklaştır
Komutlar ESP32'ye ulaşmıyorKonu adında harf farkı var ya da subscribe() yeniden bağlanınca tekrarlanmıyorKonuyu mosquitto_sub ile doğrula; subscribe() satırlarını bağlanma fonksiyonunun içine koy
Röle açılışta kendiliğinden açılıyorKomut konusunda retain'li eski bir mesaj duruyormosquitto_pub -r -n -t ev/salon/role/komut ile retain mesajını sil
Home Assistant'ta varlıklar "Kullanılamıyor"availability konusunda offline var ya da online yazımı farklıev/salon/baglanti konusunu dinle; kodun bağlanınca online yayınladığından emin ol
Değer yerine anlamsız karakterlerPayload \0 ile bitmez, length kullanılmadan okunmuşPayload'ı length kadar döngüyle kopyala
ESPHome cihazı 15 dakikada bir yeniden başlıyorMQTT modunda api: bloğu duruyor ama Home Assistant bağlanmıyorapi: bloğunu sil ya da reboot_timeout: 0s ekle
Sorun ararken sırayı koru: önce Seri Monitör'de Wi-Fi bağlantısını ve IP adresini gör, sonra bilgisayarda mosquitto_sub -v -t "#" ile broker'a gerçekten ne geldiğini izle, en son Home Assistant'a bak. Mesaj broker'da görünüyor ama Home Assistant'ta görünmüyorsa sorun keşif JSON'undadır; broker'a hiç gelmiyorsa ESP32 tarafındadır. Wi-Fi aşamasında takılıyorsan ESP32 Wi-Fi Bağlanmıyor, kart röle çekerken yeniden başlıyorsa ESP32 Brownout ve Guru Meditation rehberine göz at.

Bir broker, birkaç konu ve PubSubClient ile ESP32'n artık evin geri kalanıyla aynı dili konuşan bir akıllı ev cihazına dönüştü. Aynı yapıya yeni sensörler, başka odalar ve Pico W gibi farklı kartlar ekleyebilir, hepsini Home Assistant'tan tek panelde yönetebilirsin. BlueGrays uygulamasında ESP32 Wi-Fi bağlantısı, DHT22 ile sıcaklık ve nem ölçümü, PIR ve röleli akıllı aydınlatma, WebSocket ile gerçek zamanlı kontrol ve akıllı bitki sulama gibi projeleri devre şemaları ve kodlarıyla adım adım bulabilirsin.

Sıkça sorulan sorular

MQTT nedir, ne işe yarar?

MQTT, cihazların bir broker üzerinden konu (topic) adlarıyla mesaj alıp verdiği hafif bir mesajlaşma protokolüdür. Az bant genişliği ve az enerji harcadığı için ESP32 gibi küçük cihazların sensör verisini göndermesi ve komut alması için idealdir. Home Assistant, Node-RED ve endüstriyel IoT sistemlerinin çoğu MQTT konuşur.

MQTT hangi portu kullanır?

Şifresiz MQTT varsayılan olarak 1883, TLS ile şifrelenmiş MQTT ise 8883 portunu kullanır. Tarayıcıdan bağlanmak için kullanılan WebSocket portu broker'a göre değişir; Home Assistant'taki Mosquitto broker'da bu port 1884'tür. ESP32 ev ağında genellikle 1883'e bağlanır.

MQTT için internet gerekir mi?

Hayır. Broker evdeki bir Raspberry Pi'de ya da Home Assistant'ta çalışıyorsa ESP32 ile broker arasındaki trafik tamamen yerel ağda kalır; internet kesilse bile sensörler ve röleler çalışmaya devam eder. İnternet yalnızca evin dışından erişmek ya da bulut tabanlı bir broker kullanmak istediğinde gerekir.

ESP32 neden Home Assistant'ta görünmüyor?

En sık sebepler keşif mesajının 256 baytlık PubSubClient tamponuna sığmaması, config konusunun yanlış yazılması ya da JSON'da bir tırnak hatasıdır. mosquitto_sub ile homeassistant/# konusunu dinleyerek mesajın broker'a gelip gelmediğini kontrol et ve kodda mqtt.setBufferSize(1024) satırının bulunduğundan emin ol. Home Assistant'taki MQTT entegrasyonunun aynı broker'a bağlı olması da gerekir.

ESPHome mu, Arduino ile MQTT mi kullanmalıyım?

Amacın çalışan bir akıllı ev cihazını hızlıca kurmaksa ESPHome daha az uğraştırır: YAML yazarsın, cihaz Home Assistant'ta kendiliğinden belirir ve kablosuz güncellenir. MQTT protokolünü öğrenmek, kendi mantığını yazmak ya da Home Assistant dışındaki sistemlerle çalışmak istiyorsan Arduino ve PubSubClient daha esnektir. İkisi aynı evde sorunsuz bir arada kullanılabilir.

MQTT QoS 0, 1 ve 2 arasındaki fark nedir?

QoS 0 mesajı bir kez gönderir ve onay beklemez, QoS 1 onay gelene kadar tekrar gönderir ama mesaj iki kez ulaşabilir, QoS 2 ise dört adımlı el sıkışmayla mesajın tam olarak bir kez ulaşmasını garanti eder. Sensör ölçümleri için QoS 0, komutlar için QoS 1 yeterlidir. PubSubClient yalnızca QoS 0 ile yayın yapabilir ve QoS 0 ya da 1 ile abone olabilir.

Tüm projeleri gör
ESP32 ile LED Yakma
#103Başlangıç

ESP32 ile LED Yakma

ESP32 ile temel GPIO çıkışı kullanımını öğretir. Bir LED'i dijital pinden açıp kapatarak yanıp sönme efekti elde ederiz. Arduino UNO'daki klasik blink projesinin ESP32 versiyonu; Arduino ortamındaki temel blink komutları aynıdır, ancak ESP32'nin pin yerleşimi ve 3,3 V GPIO seviyeleri Arduino UNO'dan farklıdır.

4.7(37)
99
ESP32 Wi-Fi STA Bağlantısı (LCD Ekranlı)
#127İleri

ESP32 Wi-Fi STA Bağlantısı (LCD Ekranlı)

Bu projede ESP32'yi Station (STA) modunda evdeki Wi-Fi ağına güvenli ve hata toleranslı şekilde bağlıyoruz. SSID/şifreyi secrets.h dosyasına ayırarak Git'e sızmasını önlüyor, otomatik yeniden bağlanma mekanizması kuruyor, RSSI sinyal seviyesini ve IP adresini I2C LCD ekranda gösteriyoruz. Dahili LED durum göstergesi olarak çalışır. Üretim seviyesi bir bağlantı yöneticisidir.

4.4(21)
34
ESP32 DHT22 Sıcaklık ve Nem (LCD Ekranlı)
#117Orta

ESP32 DHT22 Sıcaklık ve Nem (LCD Ekranlı)

DHT22 sensörü ile ortam sıcaklığını ve nem oranını ölçüp 16x2 I2C LCD ekranda gerçek zamanlı olarak gösteren bir projedir. Adafruit DHT kütüphanesi kullanılarak tek kablo (one-wire) protokolü ile sensörden veri okunur. Bu proje, IoT hava istasyonu, akıllı ev otomasyonu veya seralarda ortam takip sistemlerinin temelini oluşturur. ESP32'nin GPIO 4 pini üzerinden DHT22 ile haberleşme sağlanır.

4.8(38)
56
ESP32 Akıllı Aydınlatma (PIR + LDR + Röle + OLED)
#141İleri
Premium

ESP32 Akıllı Aydınlatma (PIR + LDR + Röle + OLED)

ESP32, PIR hareket sensörü, LDR ışık sensörü ve röle modülü ile evinin koridorunu, tuvaletini veya kilerini akıllı aydınlatmaya dönüştürüyoruz. Klasik "karanlıkta hareket algılanınca ışık yansın" senaryosunu inşa ediyoruz — ortam aydınlıksa hareket olsa bile ışık yanmaz, böylece gündüz gereksiz yere yanmaz ve enerji tasarrufu sağlanır. Işık 30 saniye yanık kalır; hareket devam ederse timer otomatik sıfırlanır ve süre uzar. SSD1306 OLED ekranda büyük fontlarla durum (AÇIK / GÜNDÜZ / BEKLE), geri

4.3(6)
11
ESP32 WebSocket Sayaç (2 Buton + LCD + Web Realtime)
#130İleri
Premium

ESP32 WebSocket Sayaç (2 Buton + LCD + Web Realtime)

Bu projede ESP32'ye bağlı iki butonla (GPIO 5 artırır, GPIO 4 azaltır) bir sayaç değiştirilir. Değer hem 16x2 I2C LCD'de hem de ESPAsyncWebServer'ın WebSocket desteğiyle bağlı tüm tarayıcılarda anında güncellenir; sayfayı yenilemek gerekmez. HTTP polling yerine tek bir kalıcı bağlantı kullanılır ve ESP32 yeni değeri ws.textAll() ile herkese gönderir.

4.5(14)
23
ESP32 mDNS: bluegrays-esp.local ile Cihaza Erişim (LCD Ekranlı)
#131İleri
Premium

ESP32 mDNS: bluegrays-esp.local ile Cihaza Erişim (LCD Ekranlı)

Bu projede ESP32'ye mDNS (Multicast DNS) servisi ekleyerek IP adresi yerine bluegrays-esp.local gibi okunabilir bir host adıyla erişim sağlıyoruz. DHCP'nin verdiği IP değişse bile cihaza her zaman aynı isimle ulaşabilirsiniz. Üzerinde küçük bir web server da çalıştırarak tarayıcıdan http://bluegrays-esp.local/ adresiyle LED kontrolü gönderiyoruz. I2C LCD ekranda hostname, IP ve LED durumu hem Türkçe hem İngilizce gösterilir. iOS, macOS ve Linux mDNS'i doğal olarak destekler; Windows'ta Bonjo

4.8(14)
23
ESP32 Hareket Alarm Sistemi (PIR + Buzzer + LED + Telegram)
#145İleri
Premium

ESP32 Hareket Alarm Sistemi (PIR + Buzzer + LED + Telegram)

PIR sensörü hareket algıladığında buzzer ve LED'i aktif eden, aynı anda Telegram üzerinden sahibine anlık bildirim gönderen akıllı bir güvenlik alarm sistemidir. Tekrarlayan alarmların sıklığını sınırlamak için 30 saniyelik cooldown (bekleme süresi) mekanizması vardır; bu mekanizma PIR sensörünün yanlış algılamalarını doğrulamaz veya ortadan kaldırmaz. Ev güvenliği, garaj izleme, depo veya çalışma odası gibi alanlarda kullanılabilir. Telegram entegrasyonu sayesinde nerede olursanız olun anında h

0.0(0)
9