mDNS ile Otomatik Cihaz Keşfi (Zero-Config)
Proje Amacı
Cihazın IP adresini ezberlemeden, ağdaki herkesin tarayıcıdan sabit bir isimle (örn. http://devreai-lamba.local) erişebilmesini sağlamayı öğretir — DHCP her seferinde farklı bir IP verse bile isim her zaman aynı kalır. ESP32'nin ESPmDNS kütüphanesi, WiFi ağı üzerinden Bonjour/Avahi uyumlu mDNS (multicast DNS) protokolünü çalıştıracak ağ yığınına ve işlem gücüne sahiptir. Bu protokol Arduino Uno'da çalıştırılamaz: mDNS bir ağ protokolüdür ve çalışması için TCP/IP yığını ile bir ağ arayüzü gerekir, Uno'da ikisi de bulunmaz.
Gerekli Malzemeler
- ESP32 DevKit V1 (38 pin)
- Durum LED'i
- 220Ω direnç
- Breadboard
- Jumper kablolar
Gerekli Kütüphaneler
ESPmDNS.h, WiFi.h, WebServer.h (üçü de ESP32 core ile gelir, ek kurulum gerekmez).
Pin Bağlantıları
| Bileşen Pini | Bağlantı |
|---|---|
| LED anot (220Ω) | GPIO4 |
| LED katot | GND |
Devre Şeması
ESP32 Kodu
| 1 | #include <WiFi.h> |
| 2 | #include <ESPmDNS.h> |
| 3 | #include <WebServer.h> |
| 4 | |
| 5 | const char* ssid = "WIFI_ADINIZ"; |
| 6 | const char* password = "WIFI_SIFRENIZ"; |
| 7 | const char* mdnsAdi = "devreai-lamba"; // erişim: http://devreai-lamba.local |
| 8 | const int LED = 4; |
| 9 | |
| 10 | WebServer server(80); |
| 11 | bool ledDurum = false; |
| 12 | |
| 13 | void anaSayfa() { |
| 14 | String html = "<html><body style='font-family:sans-serif;text-align:center;padding-top:40px'>"; |
| 15 | html += "<h2>DevreAI Lamba</h2><p>Durum: " + String(ledDurum ? "ACIK" : "KAPALI") + "</p>"; |
| 16 | html += "<a href='/ac'><button style='padding:12px 24px;font-size:16px'>AC</button></a> "; |
| 17 | html += "<a href='/kapat'><button style='padding:12px 24px;font-size:16px'>KAPAT</button></a>"; |
| 18 | html += "</body></html>"; |
| 19 | server.send(200, "text/html", html); |
| 20 | } |
| 21 | |
| 22 | void setup() { |
| 23 | Serial.begin(115200); |
| 24 | pinMode(LED, OUTPUT); |
| 25 | |
| 26 | WiFi.begin(ssid, password); |
| 27 | Serial.print("WiFi'ye bağlanıyor"); |
| 28 | while (WiFi.status() != WL_CONNECTED) { delay(400); Serial.print("."); } |
| 29 | Serial.println("\nBağlandı: " + WiFi.localIP().toString()); |
| 30 | |
| 31 | if (MDNS.begin(mdnsAdi)) { |
| 32 | Serial.printf("mDNS başlatıldı: http://%s.local\n", mdnsAdi); |
| 33 | MDNS.addService("http", "tcp", 80); // ağdaki diğer cihazların bu servisi keşfetmesini sağlar |
| 34 | } else { |
| 35 | Serial.println("mDNS başlatılamadı!"); |
| 36 | } |
| 37 | |
| 38 | server.on("/", anaSayfa); |
| 39 | server.on("/ac", []() { ledDurum = true; digitalWrite(LED, HIGH); anaSayfa(); }); |
| 40 | server.on("/kapat", []() { ledDurum = false; digitalWrite(LED, LOW); anaSayfa(); }); |
| 41 | server.begin(); |
| 42 | } |
| 43 | |
| 44 | void loop() { |
| 45 | server.handleClient(); // mDNS.update() ESP32 core'da otomatik/gerekli değildir |
| 46 | } |
Çalışma Açıklaması
mDNS aynı lokal ağ segmentinde çalışır — farklı bir alt ağdan veya internetten '.local' adresiyle erişim mümkün değildir; bu bir eksiklik değil, protokolün tasarım gereği taşıdığı bir sınırlamadır. iOS/macOS cihazlar mDNS'i (Bonjour) yerleşik olarak destekler; bazı Android/Windows cihazlarda ek bir uygulama (Bonjour Print Services vb.) gerekebilir, bu yüzden çok platformlu bir ortamda test etmek faydalıdır.
Test Bilgisi
Kodu yükleyin, Seri Monitör'den gerçek IP'yi not edin (karşılaştırma amaçlı). Aynı WiFi ağındaki bir telefon veya bilgisayardan tarayıcıya IP yerine 'http://devreai-lamba.local' yazın; sayfa açılıp AÇ/KAPAT butonlarıyla LED'i kontrol edebilmelisiniz. Router'ı yeniden başlatıp cihazın gerçek IP'sinin değiştiğini ama '.local' adresinin hâlâ sorunsuz çalıştığını doğrulayın — mDNS'in asıl değeri bu senaryoda ortaya çıkar.
Olası Sorunlar ve Çözümleri
'.local' adresi açılmıyorsa: cihazınızın işletim sisteminin mDNS desteklediğinden emin olun (Windows 10 öncesi sürümlerde genelde çalışmaz), alternatif olarak IP adresiyle test edip sorunun mDNS'te mi ağda mı olduğunu ayırt edin. MDNS.begin() başarısız oluyorsa: mdnsAdi içinde boşluk veya özel karakter olmadığından emin olun, sadece harf-rakam-tire kullanın. Aynı isimde birden fazla cihaz aynı ağda varsa: mDNS isim çakışması yaşanır, her cihaza benzersiz bir isim verin (örn. WiFi.macAddress()'in son dört hanesini isme eklemek).
Alternatif Çözümler
MDNS.addService() ile birden fazla servis (örn. hem 'http' hem özel bir 'devreai' servis tipi) ilan edilerek cihaz keşfi daha zengin hale getirilebilir. Bir mobil veya masaüstü uygulamasında mDNS tarayıcı (Bonjour Browser benzeri) kullanılarak ağdaki tüm DevreAI cihazlarını otomatik listeleyen bir kontrol paneli yapılabilir. mDNS ile birlikte proje #06'daki ESPAsyncWebServer kullanılarak hem keşif hem bloklamayan bir API aynı cihazda birleştirilebilir.
Benzer Projeler
WiFiManager ile Captive Portal Kurulum Sihirbazı
Cihazı ilk açılışta WiFi ağı bilgisi olmadan bir Erişim Noktası (AP) moduna geçirip, telefon veya bilgisayarla bu ağa bağlanan kullanıcıya otomatik açılan bir web sayfasından (captive portal) ev WiFi bilgilerini girdirmeyi öğretir — kod içine SSID/şifre yazmadan, kutudan çıkar çıkmaz kurulum yapılabilen tüketici ürünlerindeki deneyimin bir benzeri. ESP32'nin WiFi çipi Erişim Noktası (AP) ve İstemci (STA) modları arasında yazılımsal olarak geçiş yapabilir ve bu esnada aynı anda basit bir DNS yönlendirme + web sunucusunu çalıştıracak yeterli RAM'e sahiptir. Bu senaryo Arduino Uno'da kurulamaz: kart hiçbir WiFi radyo donanımı içermez ve harici bir WiFi shield eklense bile 2KB RAM'i, DNS yönlendirme + web sunucusu + form işleme arabelleklerini aynı anda tutmaya yetmez.
NTP Zaman Senkronizasyonlu Otomatik Eylem Planlayıcı
WiFi üzerinden NTP (Network Time Protocol) sunucusuyla gerçek dünya saatini senkronize edip, bu saate göre belirli zamanlarda (örn. her gün 07:00 ve 19:00) bir röleyi otomatik tetiklemeyi öğretir — harici bir RTC modülüne veya manuel saat girişine hiç gerek kalmadan. ESP32'nin WiFi bağlantısı sayesinde configTime() ile saniyeler içinde internetten doğru zamanı alıp dahili saatini senkronize edebilir. Arduino Uno'da aynı otomatiklik sağlanamaz: kartın NTP sunucusuna ulaşacak hiçbir ağ bağlantısı yoktur; zaman bilgisi için mutlaka harici bir pilli RTC modülü (DS3231 gibi) eklenip elle veya USB üzerinden bir kerelik saat ayarlanması gerekir, kendiliğinden senkronizasyon mümkün değildir.
OTA Kablosuz Firmware Güncelleme Sistemi
ESP32'nin dahili çift OTA (Over-The-Air) flash partisyon şemasını kullanarak, sahaya kurulmuş bir cihaza tekrar USB kablosu takmadan tamamen kablosuz şekilde yeni firmware yüklemeyi öğretir — özellikle tavana, duvara veya erişimi zor bir noktaya monte edilmiş onlarca cihazı yönetirken zaman ve emek kazandıran pratik bir yetenektir. ESP32'nin flash belleği kalkınma sırasında bir 'factory' bölümü ile iki ayrı OTA partisyonuna bölünebilir; cihaz yeni kodu ağdan indirip o an boş olan partisyona yazar, bütünlük kontrolünden geçerse oradan açılış yapar ve önceki çalışan sürüm otomatik olarak yedek konumunda kalır, böylece yarım kalan veya bozuk bir güncelleme cihazı kullanılamaz hale getirmez. Bu iki katmanlı flash mimarisi ESP32'ye özgüdür: Arduino Uno'nun ATmega328P'sinde toplam flash belleği zaten 32KB'dir ve sketch kodunun kendisi bu alanın büyük bölümünü kapladığından ikinci bir tam firmware kopyasına yer kalmaz; kartta WiFi donanımı da bulunmadığından ağ üzerinden güncelleme almak zaten söz konusu değildir.