ESP32 ve Arduino

PubSubClient rc=-2 ve Diğer Durum Kodları Açıklamalı (Çözümleriyle)

PubSubClient yalnızca "failed, rc=-2" mi yazıyor? Bu rehber -4 ile 5 arasındaki tüm durum kodlarını çözümlüyor ve DNS, port, TLS, client ID ve kimlik bilgisi sorunları için denenmiş çözümler sunuyor.

Bir ESP32 kartının yanında PubSubClient rc=-2 bağlantı hatasını gösteren seri monitör
Bunu kendi MQTT broker’ınızda çalıştırınFree planla özel, yönetilen bir MQTT broker alın ve hazır kod örnekleriyle başlayın.
Ücretsiz deneyin Kod örnekleri Kart gerekmez

Seri monitörde failed, rc=-2 görmek en yaygın PubSubClient hatasıdır ve bu mesaj tek başına size çok az şey söyler. PubSubClient rc=-2, broker'a giden TCP (veya TLS) bağlantısının hiç açılamadığı anlamına gelir; dolayısıyla sorun neredeyse her zaman MQTT'nin kendisinde değil, DNS'te, portta, ağda veya sertifikadadır. Bu rehber -4 ile 5 arasındaki her durum kodunu çözümler ve her biri için bir çözüm sunar.

rc Değeri Nereden Gelir?

PubSubClient son bağlantı denemesinin sonucunu, mqtt.state() ile okuduğunuz dahili bir durum değişkeninde saklar. Örnek sketch'lerin çoğu, connect() false döndürdüğünde bu değeri yazdırır:

if (!mqtt.connect(clientId)) {
  Serial.print("failed, rc=");
  Serial.println(mqtt.state());
}

Değerler PubSubClient.h içinde sabit olarak tanımlanmıştır. Negatif değerler kütüphaneden ve ağ katmanından gelir. Pozitif değerler ise broker'ın CONNACK paketinde geri gönderdiği, MQTT 3.1.1 spesifikasyonunda tanımlanan dönüş kodlarıdır.

rc Sabit Katman Sade anlamı
-4 MQTT_CONNECTION_TIMEOUT Kütüphane Soket açıldı ama zamanında CONNACK (veya ping yanıtı) gelmedi
-3 MQTT_CONNECTION_LOST Ağ Kurulmuş bir bağlantı koptu
-2 MQTT_CONNECT_FAILED Ağ Soket hiç açılamadı
-1 MQTT_DISCONNECTED Kütüphane Client düzgün şekilde bağlantıyı kesti
0 MQTT_CONNECTED Broker Bağlı
1 MQTT_CONNECT_BAD_PROTOCOL Broker Protokol sürümü kabul edilmedi
2 MQTT_CONNECT_BAD_CLIENT_ID Broker Client ID reddedildi
3 MQTT_CONNECT_UNAVAILABLE Broker Broker şu anda bağlantı kabul edemiyor
4 MQTT_CONNECT_BAD_CREDENTIALS Broker Kullanıcı adı veya parola yanlış
5 MQTT_CONNECT_UNAUTHORIZED Broker Bağlanma yetkisi yok

Asıl önemli nokta şu: negatif kodlarda broker sizi ya hiç görmedi ya da hiç yanıt vermedi. Pozitif kodlarda ise broker CONNECT paketinizi aldı ve bilinçli olarak reddetti.

PubSubClient rc=-2 Hatasını Çözmek

rc=-2, alttaki ağ nesnesinde client.connect(host, port) her başarısız olduğunda raporlandığı için pek çok olası nedeni vardır. Bunları şu sırayla kontrol edin.

1. Wi-Fi Aslında Bağlı Değil

WiFi.status() == WL_CONNECTED olmadan önce mqtt.connect() çağırmak her zaman -2 döndürür. Bu durum, erişim noktası bağlantınızı düşürdüğünde ve döngünüz yalnızca MQTT'yi kontrol ettiğinde de yaşanır. Her döngüde önce Wi-Fi'yi kontrol edin ve MQTT'ye dokunmadan önce Wi-Fi'yi yeniden bağlayın.

2. DNS Başarısız veya Host Adı Yanlış

Sonunda boşluk bulunan broker.connectmq.com gibi yazım hataları, mqtt://broker.connectmq.com (host adı yerine URL) veya http:// önekleri sessizce başarısız olur. setServer() yalın bir host adı veya bir IPAddress bekler. DNS'i doğrudan test edin:

IPAddress ip;
if (WiFi.hostByName("broker.connectmq.com", ip)) {
  Serial.print("Resolved to ");
  Serial.println(ip);
} else {
  Serial.println("DNS lookup failed");
}

DNS başarısız olursa DHCP'nin size bir DNS sunucusu verip vermediğini kontrol edin veya WiFi.config() ile açıkça bir DNS sunucusu ayarlayın.

3. Client Türü İçin Yanlış Port

Bu klasik hatadır. Port ile ağ client'ı birbirine uymalıdır:

Port Taşıma Kullanılacak Arduino client'ı
1883 TCP üzerinden düz MQTT WiFiClient
8883 TLS üzerinden MQTT WiFiClientSecure
8083 / 8084 WebSocket üzerinden MQTT PubSubClient tarafından desteklenmez

8883'e yönlendirilmiş bir WiFiClient bir TCP soketi açar, ardından broker TLS el sıkışması beklediği için takılır veya başarısız olur; bu çoğu zaman -2 veya -4 olarak görünür. 1883'e yönlendirilmiş bir WiFiClientSecure ise el sıkışmada başarısız olur ve -2 döndürür. PubSubClient WebSocket konuşamaz; bu yüzden 8083 ve 8084 portları tarayıcılar ve WebSocket üzerinden MQTT yazısında anlatılan araçlar içindir.

4. TLS Sertifika Sorunları

WiFiClientSecure ile başarısız bir sertifika doğrulaması da rc=-2 olarak raporlanır. Yaygın nedenler:

  • CA sertifikası ayarlanmamış. ESP32'de, broker sertifikasını imzalayan kök sertifikayla setCACert() çağırın. ConnectMQ Let's Encrypt kullanır, dolayısıyla kök sertifika ISRG Root X1'dir.
  • O tarihten bu yana yenilenmiş bir yaprak (leaf) veya ara sertifikayı sabitlemek (pinning). Let's Encrypt sertifikalarının ömrü kısadır; yaprağı değil kökü sabitleyin.
  • ESP8266'da yanlış sistem saati. BearSSL geçerlilik tarihlerini kontrol eder, bu nedenle bağlanmadan önce saati configTime() ile senkronize edin.
  • Yetersiz bellek. TLS el sıkışması heap'ten azımsanmayacak bir pay ister; ESP8266'da büyük bir MQTT buffer'ı ile TLS birlikte belleği tüketebilir.

ESP32'de başarısız bir denemeden sonra alttaki TLS hatasını yazdırabilirsiniz:

char err[128];
int code = netClient.lastError(err, sizeof(err));
Serial.printf("TLS error %d: %s\n", code, err);

Sorunu izole etmek için geçici olarak netClient.setInsecure() çağırın. Böyle bağlanıyorsa sorun sertifika yapılandırmanızdadır. setInsecure() içeren bir firmware'i asla yayına almayın.

5. Ağ Giden MQTT Trafiğini Engelliyor

Kurumsal, okul ve bazı misafir ağları giden 1883 ve 8883 portlarını engeller. Aynı sketch'i bir telefon hotspot'unda deneyin. Orada çalışıyorsa portun açılmasını isteyin veya cihazı farklı bir ağ segmentine taşıyın.

6. Çok Sık Bağlanmaya Çalışmak

Broker IP adresinizden tekrar tekrar başarısız denemeler görürse bağlantıları geçici olarak reddedebilir. Örneğin ConnectMQ, tenant'ları korumak için tekrarlanan başarısız girişlerden sonra IP adreslerini engeller. Gecikmesiz bir yeniden bağlanma döngüsü, tek bir yanlış parolayı rc=-2 gibi görünen bir kilitlenmeye dönüştürebilir. Denemeler arasında her zaman en az birkaç saniye bekleyin ve birkaç başarısızlıktan sonra bekleme süresini daha da artırın.

rc=-4 (Bağlantı Zaman Aşımı) Hatasını Çözmek

Burada soket açılmıştır ama CONNACK, soket zaman aşımı süresi (varsayılan olarak 15 saniye) içinde gelmemiştir. Tipik nedenler:

  • Yukarıda anlatıldığı gibi, TLS portunda düz WiFiClient kullanmak.
  • Yoğun paket kaybı olan zayıf Wi-Fi sinyali. WiFi.RSSI() değerini yazdırın; -80 dBm civarı veya daha zayıf her değer güvenilmezdir.
  • Engelleyici (blocking) kod. Bağlantı daha önce kurulduysa, keep alive ping'lerinin yanıtlanması için loop() yeterince sık çağrılmadığında -4 daha sonra da ortaya çıkabilir.

rc=-3 (Bağlantı Koptu) Hatasını Çözmek

Bağlantı çalıştı, sonra koptu. Şunlara bakın:

  • Yinelenen client ID'ler. İkinci bir cihaz aynı ID ile bağlandığında broker ilkini düşürür. Aynı sketch ile yüklenmiş iki kart sırayla birbirini dışarı atar. ID'leri MAC adresinden üretin.
  • Keep alive süresinin dolması. Uzun delay() çağrıları veya yavaş sensör okumaları mqtt.loop() çağrısını aç bırakır.
  • Aşırı büyük veya çok sık mesajlar. Broker'lar limit uygular. broker.connectmq.com adresindeki herkese açık MQTT test broker'ında client'lar mesaj başına 64 KB ve saniyede 10 mesajla sınırlıdır; limitlerin aşılması oturumun kapanmasına yol açabilir.

Pozitif Kodları (1 ile 5 Arası) Çözmek

rc=1: Hatalı Protokol

PubSubClient varsayılan olarak MQTT 3.1.1 gönderir. Bu kodu yalnızca MQTT_VERSION değerini 3.1 olarak derleyip bunu reddeden bir broker'a bağlandıysanız görürsünüz. Bu ayarı kaldırın.

rc=2: Client ID Reddedildi

Genellikle suçlu boş bir client ID'dir. ConnectMQ herkese açık broker'ı, anonim bağlantılarda bile boş olmayan bir client ID gerektirir. Özel bir ConnectMQ broker'ında client ID'ler portalda verilen kimlik bilgilerine bağlıdır; bu yüzden size verilen client ID'yi birebir kullanın.

rc=3: Sunucu Kullanılamıyor

Broker çalışıyor ama bağlantı kabul etmiyor; örneğin bakım sırasında veya bir bağlantı kotasına ulaşıldığında. Bekleyip yeniden deneyin. Kendi broker'ınızda devam ediyorsa planınızın bağlantı limitini aşıp aşmadığınızı kontrol edin.

rc=4: Hatalı Kullanıcı Adı veya Parola

Kimlik bilgilerini portaldan yeniden kopyalayın ve görünmez karakterlere dikkat edin. connect(id, user, pass) fonksiyonunun önce client ID aldığını unutmayın; sıranın karıştırılması şaşırtıcı derecede yaygındır.

rc=5: Yetkisiz

Broker kimlik bilgilerini anladı ama bu client'ı reddediyor; örneğin kullanıcı adı ile client ID birbirine ait olmadığı için. Üç değeri de yeniden kontrol edin.

Tanılama Amaçlı Bir Connect Fonksiyonu

Çıplak bir sayı yerine okunabilir bir neden almak için bunu herhangi bir sketch'e ekleyin:

const char* mqttStateText(int s) {
  switch (s) {
    case -4: return "timeout (no CONNACK) - check port/TLS match and signal";
    case -3: return "connection lost - duplicate client ID or keep alive";
    case -2: return "socket failed - Wi-Fi, DNS, port, firewall or TLS cert";
    case -1: return "disconnected";
    case 0:  return "connected";
    case 1:  return "bad protocol version";
    case 2:  return "client ID rejected - empty or not allowed";
    case 3:  return "server unavailable - retry later";
    case 4:  return "bad username or password";
    case 5:  return "not authorised";
    default: return "unknown";
  }
}

bool connectWithDiagnostics() {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Wi-Fi not connected, skipping MQTT");
    return false;
  }
  if (mqtt.connect(DEVICE_ID)) {
    Serial.println("MQTT connected");
    return true;
  }
  int s = mqtt.state();
  Serial.printf("MQTT failed rc=%d: %s\n", s, mqttStateText(s));
  return false;
}

Hızlı İzolasyon Kontrol Listesi

  1. Bilgisayarınız broker'a ulaşabiliyor mu? mosquitto_sub -h broker.connectmq.com -p 1883 -i test-$RANDOM -t "connectmq/demo/check/#" -v komutunu çalıştırın. Bu başarısız olursa sorun kartta değil, ağınızdadır.
  2. Kart host adını çözümleyebiliyor mu? Yukarıdaki DNS kod parçasını kullanın.
  3. WiFiClient ve anonim, benzersiz bir client ID ile 1883'te bağlanıyor mu? Evetse sorun TLS'te veya kimlik bilgilerindedir.
  4. setInsecure() ile 8883'te bağlanıyor mu? Evetse CA sertifikasını düzeltin.
  5. CA ile bağlanıyor ama kimlik bilgileriyle başarısız mı oluyor? Kullanıcı adını, parolayı ve client ID'yi yeniden kontrol edin.

Bağlandıktan sonra insanların karşılaştığı bir sonraki sorun mesaj boyutudur; bkz. PubSubClient buffer boyutu. Kütüphanenin eksiksiz anlatımı için PubSubClient Arduino eğitimimizi, eksiksiz bir proje için ise ESP32 IoT eğitimi ana rehberini okuyun.

Yönetilen Bir Broker ile rc Kodlarının Peşinden Koşmayı Bırakın

rc=-2 ve rc=-4 hatalarının çoğu, süresi dolmuş sertifikalara, kapalı güvenlik duvarı portlarına veya çökmüş servislere sahip kendi barındırdığınız broker'lardan kaynaklanır. ConnectMQ gibi tam yönetilen bir MQTT servisi bu değişkenleri ortadan kaldırır: otomatik yenilenen Let's Encrypt sertifikasıyla 8883'te TLS, sizin için oluşturulan kimlik bilgileri ve portalda, cihazda hata ayıklamaya başlamadan önce broker tarafının çalıştığını doğrulayabilmeniz için bir tarayıcı MQTT client'ı. app.connectmq.com adresinde ücretsiz bir Serverless broker başlatın, kredi kartı gerekmez.

Sık Sorulan Sorular

PubSubClient'ta rc=-2 ne anlama gelir?

Broker'a ağ bağlantısının açılamadığı anlamına gelir. Broker CONNECT paketinizi hiç almadı; bu yüzden Wi-Fi'yi, DNS'i, portu ve TLS kullanıyorsanız CA sertifikasını kontrol edin.

Neden yalnızca 8883 portunda rc=-2 alıyorum?

TLS kurulumunuz başarısız oluyor. WiFiClientSecure kullandığınızdan, doğru kök sertifikayı (Let's Encrypt kullanan broker'lar için ISRG Root X1) yüklediğinizden ve ESP8266'da bağlanmadan önce saati ayarladığınızdan emin olun.

Kartım bağlanıyor, sonra birkaç saniyede bir rc=-3 gösteriyor. Neden?

Çoğu zaman başka bir cihaz veya araç aynı client ID'yi kullanıyordur; bu yüzden broker bir oturumu sürekli diğeriyle değiştirir. Her cihaza, örneğin MAC adresine dayalı, benzersiz bir ID verin.

rc=5, rc=4'ten farklı mı?

Evet. rc=4 kullanıcı adının veya parolanın yanlış olduğu anlamına gelir. rc=5 ise kimlik bilgilerinin anlaşıldığı ama bu client'ın bağlanmasına izin verilmediği anlamına gelir; bunun nedeni çoğu zaman client ID'nin kimlik bilgileriyle eşleşmemesidir.

İlgili yazılar

ESP32 NTP MQTT Zaman Damgası: Her Mesaja Doğru Zaman Ekleyin

ESP32 saatini NTP ile eşitleyin, ISO 8601 ve epoch milisaniye zaman damgalarını biçimlendirin ve bunları MQTT payload'larına ekleyin; böylece ölçümler geç yayınlansa bile gerçek alınma zamanlarını korur.

6 dk okuma

Tüm yazılar →

Özel MQTT broker’ınız birkaç tık uzağınızda

Hesabınızı oluşturun, broker kimlik bilgilerinizi alın ve ilk cihazınızı bağlayın — kurulacak, yamalanacak ya da ölçeklendirilecek sunucu yok.