ESP32'niz bir MQTT broker'a bağlanamadığında neden neredeyse her zaman, yanlış Wi-Fi bandından düz bir porttaki TLS istemcisine kadar uzanan, öngörülebilir bir düzine sorundan biridir. Bu rehber size sistematik bir kontrol sırası sunar, her PubSubClient hata kodunun ne anlama geldiğini açıklar ve her düzeltmenin broker.connectmq.com üzerinde nasıl doğrulanacağını gösterir.
Hata Koduyla Başlayın
Herhangi bir şeyi değiştirmeden önce bağlantının nerede başarısız olduğunu bulun. PubSubClient nedeni client.state() aracılığıyla bildirir. connect() her false döndürdüğünde bunu yazdırın:
if (!mqtt.connect(clientId.c_str())) {
Serial.printf("MQTT connect failed, state=%d\n", mqtt.state());
}
state() |
Sabit | Genellikle ne anlama gelir |
|---|---|---|
| -4 | MQTT_CONNECTION_TIMEOUT |
Sunucu keepalive süresi içinde yanıt vermedi |
| -3 | MQTT_CONNECTION_LOST |
Bağlantı kurulduktan sonra koptu |
| -2 | MQTT_CONNECT_FAILED |
TCP veya TLS bağlantısı hiç açılamadı |
| -1 | MQTT_DISCONNECTED |
İstemcinin bağlantısı düzgünce kesildi |
| 1 | MQTT_CONNECT_BAD_PROTOCOL |
Broker protokol sürümünü kabul etmiyor |
| 2 | MQTT_CONNECT_BAD_CLIENT_ID |
Client ID reddedildi |
| 3 | MQTT_CONNECT_UNAVAILABLE |
Broker kullanılamıyor |
| 4 | MQTT_CONNECT_BAD_CREDENTIALS |
Yanlış kullanıcı adı veya parola |
| 5 | MQTT_CONNECT_UNAUTHORIZED |
İstemci yetkili değil |
Bu ayrım işe yarar: negatif kodlar sorunun MQTT'nin altında (ağ, DNS, TCP, TLS) olduğunu, pozitif kodlar ise broker'ın yanıt verip sizi reddettiğini gösterir. -2 sizi 1–6 numaralı çözümlere, 4 veya 5 ise 7–9 numaralı çözümlere yönlendirir.
Önce Broker Tarafının Çalıştığını Kanıtlayın
Firmware'e dokunmadan önce broker'ı olası nedenler arasından çıkarın. Aynı ağdaki bir bilgisayardan şunu çalıştırın:
mosquitto_sub -h broker.connectmq.com -p 1883 -i pc-test-4821 -t 'connectmq/demo/4821/#' -v
İkinci bir terminalde:
mosquitto_pub -h broker.connectmq.com -p 1883 -i pc-pub-4821 -t connectmq/demo/4821/hello -m test
Mesaj ulaşırsa broker ve internet yolu çalışıyordur; sorun ESP32'de veya onun ağ segmentindedir. Bilgisayarınızdan da ulaşmıyorsa önce ağınızın güvenlik duvarını kontrol edin. Herkese açık MQTT test broker'ı sayfası test edebileceğiniz portları ve sınırları listeler.
Ağ Seviyesindeki Çözümler (Negatif Durum Kodları)
1. Wi-Fi'ın 2,4 GHz'de Gerçekten Bağlı Olduğundan Emin Olun
ESP32 (5 GHz destekli yeni varyantlar hariç) yalnızca 2,4 GHz ağlarla konuşur. Her iki bant için tek SSID kullanan çift bantlı bir router genellikle çalışır, ancak yalnızca 5 GHz olan bir SSID asla çalışmaz. İşlem sırasını da kontrol edin: WiFi.status() == WL_CONNECTED olmadan önce mqtt.connect() çağırmak her zaman -2 ile başarısız olur. WiFi.localIP() ve WiFi.RSSI() değerlerini yazdırın; yaklaşık -80 dBm'den zayıf bir sinyal, broker sorunu gibi görünen aralıklı hatalara yol açar.
2. DNS Çözümlemesini Kontrol Edin
Hostname çözümlenmezse TCP bağlantısı hiç başlamaz. Doğrudan test edin:
IPAddress ip;
if (WiFi.hostByName("broker.connectmq.com", ip)) {
Serial.println(ip);
} else {
Serial.println("DNS lookup failed");
}
Buradaki bir hata, DHCP'nin sağladığı DNS sunucusuna veya DNS girişi olmayan bir statik IP yapılandırmasına işaret eder. Statik adres için WiFi.config() kullandığınızda ağ geçidini ve bir DNS sunucusunu da verin.
3. Portu İstemci Sınıfıyla Eşleştirin
Bu tek başına en yaygın hatadır. WiFiClient düz TCP konuşur ve 1883 portunu kullanmalıdır. WiFiClientSecure TLS konuşur ve 8883 portunu kullanmalıdır. Bunları karıştırmak, başka hiçbir ipucu vermeden -2 veya -4 üretir.
| İstemci sınıfı | Port | Taşıma |
|---|---|---|
WiFiClient |
1883 | TCP üzerinden düz MQTT |
WiFiClientSecure |
8883 | TLS üzerinden MQTT |
| WebSocket kütüphaneleri | 8083 / 8084 (yol /mqtt) |
WebSocket / secure WebSocket üzerinden MQTT |
PubSubClient WebSocket konuşmaz; bu yüzden 8083 ve 8084 portları yalnızca tarayıcı istemcileri ve WebSocket destekli kütüphaneler içindir.
4. TLS Sertifika Doğrulamasını Düzeltin
WiFiClientSecure ile eksik veya yanlış bir CA sertifikası el sıkışmanın sessizce başarısız olmasına neden olur. ConnectMQ bir Let's Encrypt sertifikası kullanır; bu yüzden ISRG Root X1 kökünü setCACert() ile yükleyin. Suçlunun TLS olduğunu doğrulamak için geçici olarak secureClient.setInsecure() çağırın: bağlantı birden çalışırsa CA'nız yanlıştır. setInsecure()'u üretime göndermeyin. Ayrıntılar için TLS hatasını secureClient.lastError(buf, sizeof(buf)) ile okuyun ve eksiksiz bir güvenli kurulum için SSL/TLS üzerinden ESP32 MQTT yazısına bakın.
5. TLS'e Yeterli Bellek ve Zaman Verin
TLS el sıkışmaları onlarca kilobayt heap gerektirir. Sketch'iniz büyük tamponlar, görüntü verisi veya birkaç güvenli istemci ayırıyorsa el sıkışma -2 ile başarısız olur. Bağlanmadan hemen önce ESP.getFreeHeap() yazdırın. Saati de kontrol edin: sertifika doğrulaması tarihleri karşılaştırır ve bazı kütüphaneler geçerli bir saat ister. Bağlanmadan önce configTime() ile NTP eşitlemesi yapmak, kafa karıştırıcı hataların bütün bir sınıfını önler.
6. Ağ Yolunda Engellenen Portları Kontrol Edin
Misafir Wi-Fi, kurumsal ağlar ve bazı mobil hotspot'lar giden 1883 veya 8883 trafiğini engeller. Yukarıdaki bilgisayar testi yalnızca farklı bir ağdan çalıştıysa, ESP32'yi bir telefon hotspot'unda deneyin. Orada bağlanıyorsa asıl ağ MQTT portlarını filtreliyordur ve bunları açması için ağ yöneticisine ihtiyacınız vardır.
Broker Seviyesindeki Çözümler (Pozitif Durum Kodları)
7. Boş Olmayan, Benzersiz Bir Client ID Kullanın
Her istemcinin kendi client ID'sine ihtiyacı vardır. Aynı sabit kodlanmış ID ile yüklenen iki cihaz birbirini broker'dan tekrar tekrar düşürür; bu da -3 durumuyla rastgele kopmalar gibi görünür. Boş bir client ID de broker.connectmq.com'un public alanı dahil birçok broker tarafından reddedilir. ID'yi çipin MAC adresinden türetin:
String clientId = "esp32-" + String((uint32_t)ESP.getEfuseMac(), HEX);
8. Portaldaki Kimlik Bilgilerini ve Client ID'yi Birebir Kullanın
Özel bir ConnectMQ broker'da client ID, verilen kimlik bilgilerine bağlıdır. Oluşturulan kullanıcı adı ve parolayı kullanırken kendi client ID'nizi uydurursanız, parola doğru olsa bile broker bağlantıyı 5 koduyla reddeder. Üç değeri de portaldan kopyalayın: YOUR_CLIENT_ID, YOUR_USERNAME, YOUR_PASSWORD. Koda yapıştırırken görünmeyen sondaki boşluklara dikkat edin.
9. Engellenmeden Önce Yeniden Deneme Fırtınalarını Durdurun
Gecikmesiz bir yeniden bağlanma döngüsü broker'a saniyede çok sayıda bağlantı denemesi gönderebilir. Yanlış kimlik bilgileriyle bu özellikle zararlıdır; çünkü ConnectMQ, flood korumasının bir parçası olarak tekrarlanan başarısız girişlerden sonra IP adreslerini engeller. Denemeler arasında bekleyin ve her başarısızlıktan sonra gecikmeyi artırın:
unsigned long nextAttempt = 0;
unsigned long backoff = 2000;
void ensureMqtt() {
if (mqtt.connected() || millis() < nextAttempt) return;
if (mqtt.connect(clientId.c_str())) {
backoff = 2000;
mqtt.subscribe("connectmq/demo/4821/cmd");
} else {
Serial.printf("connect failed, state=%d, retry in %lu ms\n", mqtt.state(), backoff);
nextAttempt = millis() + backoff;
backoff = min(backoff * 2, 60000UL);
}
}
Engellemeyen yapı aynı zamanda loop()'un yanıt verebilir kalmasını sağlar. ESP32 MQTT yeniden bağlanma rehberi sağlam yeniden bağlanma mantığını daha derinlemesine ele alır.
Bağlandıktan Sonra Kopan Bağlantılar İçin Çözümler
10. mqtt.loop()'u Yeterince Sık Çağırın
PubSubClient keepalive ping'lerini yalnızca loop() içinde gönderir ve gelen paketleri yalnızca orada okur. Keepalive aralığından (varsayılan 15 saniye) uzun bir delay() veya engelleyen bir sensör okuması broker'ın istemcinin öldüğünü düşünmesine neden olur ve -3 ya da -4 görürsünüz. Uzun gecikmeleri millis() zamanlayıcılarıyla değiştirin veya keepalive'ı mqtt.setKeepAlive(30) ile yükseltin. Kart ayrıca yeniden başlıyorsa MQTT projelerinde ESP32 task watchdog sıfırlamaları hakkında okuyun.
11. Büyük Mesajlar İçin Tamponu Büyütün
PubSubClient'ın varsayılan paket tamponu, topic ve başlık dahil 256 bayttır. Daha büyük bir yayın sessizce başarısız olur: publish() false döndürür ve boyutu aşan gelen bir mesaj atılır. Bağlanmadan önce en büyük mesajınıza göre boyutlandırılmış şekilde mqtt.setBufferSize(1024) çağırın.
12. Public Broker Sınırlarına Uyun
broker.connectmq.com'un public alanı mesaj başına 64 KB, istemci başına saniyede 10 mesaj, istemci başına 10 abonelik ve en fazla 8 topic seviyesine izin verir. Sıkı bir döngüde yayın yapan veya çok sayıda topic'e abone olan bir sketch bu sınırları aştığı için bağlantıdan düşürülebilir. Yayın hızını sınırlayın, çok sayıda tekil abonelik yerine tek bir wildcard abonelik kullanın ve connectmq/demo/4821/room/temp gibi topic'leri kısa tutun.
Bir Teşhis Sketch'i
Takıldığınızda bunu yükleyin. Her aşamayı ayrı ayrı raporlar, böylece zincirin tam olarak nerede koptuğunu görürsünüz:
#include <WiFi.h>
#include <PubSubClient.h>
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* HOST = "broker.connectmq.com";
WiFiClient net;
PubSubClient mqtt(net);
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) { delay(250); Serial.print('.'); }
Serial.printf("\nWi-Fi OK ip=%s rssi=%d\n", WiFi.localIP().toString().c_str(), WiFi.RSSI());
IPAddress ip;
if (!WiFi.hostByName(HOST, ip)) { Serial.println("DNS FAILED"); return; }
Serial.printf("DNS OK %s\n", ip.toString().c_str());
if (!net.connect(HOST, 1883)) { Serial.println("TCP 1883 FAILED"); return; }
Serial.println("TCP OK");
net.stop();
String id = "esp32-diag-" + String((uint32_t)ESP.getEfuseMac(), HEX);
mqtt.setServer(HOST, 1883);
if (mqtt.connect(id.c_str())) {
Serial.println("MQTT OK");
mqtt.publish("connectmq/demo/4821/diag", "hello from diag");
} else {
Serial.printf("MQTT FAILED state=%d\n", mqtt.state());
}
}
void loop() { mqtt.loop(); }
mosquitto_sub'ı connectmq/demo/4821/# üzerinde çalışır halde tutun; her şey çalıştığı anda teşhis mesajını göreceksiniz.
Test Broker'ında Çalışıp Üretimde Çalışmıyorsa
Üretimdeki hataların çoğu 3, 4 ve 8 numaralı çözümlere dayanır: WiFiClientSecure'a geçmeden 8883 portuna geçmek, CA sertifikasını unutmak veya portal kimlik bilgileriyle kendi uydurduğunuz bir client ID kullanmak. Her seferinde tek bir şeyi değiştirin ve hata kodunu yazdırmaya devam edin. ESP32 IoT eğitimi her iki modda da sorunsuz bağlanan eksiksiz bir proje gösterir; bir MQTT broker'ın ne yaptığı yazısı da broker'ın belirli bağlantıları neden reddettiğini açıklar.
ConnectMQ ile ESP32'nizi Çevrimiçi Yapın
Cihaz test broker'ına bağlandıktan sonra onu app.connectmq.com adresinde, kredi kartı gerekmeden, ücretsiz Serverless planındaki özel bir broker'a taşıyın. Portalın tarayıcı içi MQTT istemcisi ve canlı topic gezgini, trafiği hem cihaz tarafından hem de sunucu tarafından doğrulamayı kolaylaştırır. ConnectMQ, kutudan çıktığı haliyle 8883 portunda TLS sunan yönetilen bir MQTT broker'dır; bu yüzden ESP32'de ihtiyacınız olan tek sertifika public Let's Encrypt köküdür.
Sık Sorulan Sorular
PubSubClient rc=-2 ne anlama gelir?
TCP veya TLS bağlantısının açılamadığı, dolayısıyla broker'ın hiç MQTT paketi görmediği anlamına gelir. Wi-Fi'ı, DNS'i, port ve istemci sınıfı eşleşmesini, CA sertifikasını ve boş heap'i kontrol edin.
ESP32'm neden bağlanıp birkaç saniyede bir bağlantıyı kesiyor?
Genellikle başka bir cihaz aynı client ID'yi kullanıyordur ya da mqtt.loop() keepalive ping'lerini gönderecek kadar sık çağrılmıyordur. Her cihaza benzersiz bir ID verin ve uzun engelleyen gecikmeleri kaldırın.
PubSubClient ile 8083 veya 8084 portunu kullanabilir miyim?
Hayır. Bunlar WebSocket portlarıdır ve PubSubClient yalnızca ham TCP veya TLS üzerinden MQTT konuşur. WiFiClient ile 1883'ü veya WiFiClientSecure ile 8883'ü kullanın.
Parola doğru olduğu halde kimlik bilgilerim neden reddediliyor?
Verilmiş kimlik bilgileri olan özel bir broker'da client ID bunlara bağlıdır. Oluşturulan kullanıcı adı ve parolayla birlikte portalda gösterilen client ID'yi birebir kullanın.



