IoT Eğitimleri

Tarayıcıda JavaScript ile MQTT: Tek HTML Sayfasında Minimal Bir Client

MQTT.js kullanarak güvenli WebSocket üzerinden broker.connectmq.com'a bağlanan, abone olan, yayın yapan ve canlı mesajları gösteren tek bir HTML sayfası oluşturun; derleme adımı ve backend olmadan.

Güvenli WebSocket üzerinden publish ve subscribe yapan, tarayıcıda javascript ile mqtt client'ı çalıştıran tarayıcı penceresi
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

Tarayıcıda JavaScript ile MQTT çalıştırmak, backend yazmadan canlı bir pano, uzaktan kumanda paneli veya hata ayıklama aracı geliştirmenin en hızlı yoludur. Bu eğitimde güvenli WebSocket üzerinden broker.connectmq.com adresine bağlanan, bir topic'e abone olan, mesaj yayınlayan ve bunları gerçek zamanlı gösteren, kendi kendine yeten tek bir HTML sayfası oluşturacaksınız. Ayrıca tarayıcıların MQTT için neden WebSocket'e ihtiyaç duyduğunu, CORS'un neden sorun olmadığını ve aynı sayfayı private bir broker'a nasıl güvenle taşıyacağınızı da öğreneceksiniz.

Tarayıcı Neden WebSocket Üzerinden MQTT'ye İhtiyaç Duyar?

Bir web sayfası ham TCP soketi açamaz. Tarayıcı sandbox'ı JavaScript'in ağla yalnızca HTTP(S), WebSocket, WebRTC ve birkaç yeni API üzerinden konuşmasına izin verir. Standart MQTT, 1883 portunda TCP (veya 8883'te TLS) üzerinden çalışır; bu yüzden bir tarayıcı bu portlara doğrudan ulaşamaz.

MQTT spesifikasyonu bunu, MQTT paketlerinin WebSocket ikili çerçeveleri içinde taşınmasına izin vererek çözer. Broker ek bir dinleyici sunar, tarayıcı ona bir WebSocket açar ve bundan sonra iletişim sıradan MQTT'dir: CONNECT, SUBSCRIBE, PUBLISH, PINGREQ. Protokol düzeyindeki ayrıntıları istiyorsanız WebSocket üzerinden MQTT rehberimiz el sıkışmayı ve alt protokol başlığını adım adım anlatır.

ConnectMQ her broker'da iki WebSocket dinleyicisi sunar:

Uç nokta URL Ne zaman kullanılır
WebSocket ws://broker.connectmq.com:8083/mqtt Yalnızca bir http:// sayfasından yerel test
Güvenli WebSocket wss://broker.connectmq.com:8084/mqtt https:// üzerinden sunulan her sayfa ve tüm üretim kullanımı

Varsayılan olarak wss:// kullanın. HTTPS üzerinden yüklenen bir sayfanın şifrelenmemiş bir ws:// bağlantısı açmasına izin verilmez; tarayıcı bunu, makineden tek bir paket çıkmadan karma içerik (mixed content) olarak engeller.

Peki ya CORS?

CORS (Cross-Origin Resource Sharing) fetch ve XMLHttpRequest için geçerlidir. WebSocket bağlantıları CORS preflight kontrollerine tabi değildir. Tarayıcı yükseltme (upgrade) sırasında bir Origin başlığı gönderir ve sunucu bunu incelemeyi seçebilir, ancak Access-Control-Allow-Origin dansı yoktur. Bu yüzden aşağıdaki HTML dosyasını masaüstünüzden, yerel bir geliştirme sunucusundan veya herhangi bir alan adından açabilirsiniz; proxy hilelerine gerek kalmadan bağlanır.

Kütüphane Seçimi: MQTT.js

MQTT.js, JavaScript için fiili standart MQTT client'ıdır. Aynı paket Node.js'te ve tarayıcılarda çalışır, MQTT 3.1.1 ve MQTT 5'i destekler; yeniden bağlanma, keepalive ve QoS 1 ile 2 akışlarını sizin için yönetir. Sürüm 5 önceden derlenmiş bir tarayıcı paketiyle gelir; böylece onu tek bir script etiketiyle bir CDN'den yükleyebilirsiniz. GitHub'daki MQTT.js dokümantasyonu tüm seçenekleri listeler; minimal bir client'ın ihtiyacı olan tek şey aşağıdaki alt kümedir.

Daha sonra bir bundler'a veya framework'e geçerseniz kod neredeyse hiç değişmez. Node.js ile MQTT.js rehberimiz sunucu tarafını ele alır, React MQTT eğitimi ise aynı client'ın hook'lar içine nasıl sarılacağını gösterir.

Eksiksiz Tek Sayfalık Tarayıcı MQTT JavaScript Client'ı

Aşağıdakini mqtt-client.html olarak kaydedin ve herhangi bir modern tarayıcıda açın. MQTT.js'i bir CDN'den yükler, benzersiz bir client ID ve rastgele bir topic öneki üretir ve size bağlanma, abone olma ve yayın yapma düğmeleri sunar.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Minimal MQTT Browser Client</title>
  <script src="https://unpkg.com/mqtt@5.10.1/dist/mqtt.min.js"></script>
  <style>
    body { font-family: system-ui, sans-serif; max-width: 720px; margin: 2rem auto; padding: 0 1rem; }
    input, button { font: inherit; padding: .4rem .6rem; }
    #log { border: 1px solid #ccc; height: 280px; overflow-y: auto; padding: .5rem; font-family: monospace; font-size: .85rem; }
    .row { display: flex; gap: .5rem; margin: .5rem 0; }
    .row input { flex: 1; }
  </style>
</head>
<body>
  <h1>MQTT in the Browser</h1>
  <p>Status: <strong id="status">disconnected</strong></p>

  <div class="row">
    <input id="url" value="wss://broker.connectmq.com:8084/mqtt">
    <button id="connectBtn">Connect</button>
    <button id="disconnectBtn">Disconnect</button>
  </div>

  <div class="row">
    <input id="subTopic">
    <button id="subBtn">Subscribe</button>
  </div>

  <div class="row">
    <input id="pubTopic">
    <input id="pubPayload" value='{"temperature": 21.5}'>
    <button id="pubBtn">Publish</button>
  </div>

  <div id="log"></div>

  <script>
    const randomId = Math.random().toString(16).slice(2, 10);
    const prefix = `connectmq/demo/${randomId}`;
    document.getElementById("subTopic").value = `${prefix}/#`;
    document.getElementById("pubTopic").value = `${prefix}/sensors/room1`;

    const statusEl = document.getElementById("status");
    const logEl = document.getElementById("log");
    let client = null;

    function log(text) {
      const line = document.createElement("div");
      line.textContent = `[${new Date().toLocaleTimeString()}] ${text}`;
      logEl.appendChild(line);
      logEl.scrollTop = logEl.scrollHeight;
    }

    document.getElementById("connectBtn").onclick = () => {
      if (client) return;
      const url = document.getElementById("url").value;
      client = mqtt.connect(url, {
        clientId: `browser-${randomId}`,
        protocolVersion: 5,
        clean: true,
        keepalive: 30,
        connectTimeout: 10000,
        reconnectPeriod: 3000
        // Private bir ConnectMQ broker için şunları ekleyin:
        // username: "YOUR_USERNAME",
        // password: "YOUR_PASSWORD"
      });

      client.on("connect", () => { statusEl.textContent = "connected"; log(`Connected to ${url}`); });
      client.on("reconnect", () => { statusEl.textContent = "reconnecting"; });
      client.on("close", () => { statusEl.textContent = "disconnected"; });
      client.on("offline", () => log("Client went offline"));
      client.on("error", (err) => log(`Error: ${err.message}`));
      client.on("message", (topic, payload, packet) => {
        const retained = packet.retain ? " (retained)" : "";
        log(`${topic}${retained}: ${payload.toString()}`);
      });
    };

    document.getElementById("disconnectBtn").onclick = () => {
      if (!client) return;
      client.end(false, () => log("Disconnected cleanly"));
      client = null;
    };

    document.getElementById("subBtn").onclick = () => {
      if (!client) return log("Connect first");
      const topic = document.getElementById("subTopic").value;
      client.subscribe(topic, { qos: 1 }, (err, granted) => {
        if (err) return log(`Subscribe failed: ${err.message}`);
        granted.forEach(g => log(`Subscribed to ${g.topic} (granted QoS ${g.qos})`));
      });
    };

    document.getElementById("pubBtn").onclick = () => {
      if (!client) return log("Connect first");
      const topic = document.getElementById("pubTopic").value;
      const payload = document.getElementById("pubPayload").value;
      client.publish(topic, payload, { qos: 1 }, (err) => {
        if (err) log(`Publish failed: ${err.message}`);
      });
    };
  </script>
</body>
</html>

Önce Connect'e, sonra Subscribe'a, ardından Publish'e tıklayın. Mesaj sayfanızdan broker'a gider ve doğrudan aynı sayfaya geri döner, çünkü yayın topic'iyle eşleşen prefix/# filtresine abonesiniz.

Kod Nasıl Çalışır?

Bağlanma

mqtt.connect() hemen bir client döndürür ve arka planda bağlanır. Sonrasında ne olduğunu olaylar söyler: başarılı bir CONNACK'ten sonra connect, her yeniden denemede reconnect, soket kapandığında close ve reddedilen bir oturum açma gibi sorunlar için error. protocolVersion: 5 ayarı size reason code'lar ve user property'ler gibi MQTT 5 özelliklerini sağlar; 3.1.1'e dönmek için kaldırın.

Client ID her sayfa yüklemesinde üretilir. Public broker boş olmayan herhangi bir client ID'yi kabul eder, ancak aynı ID'ye sahip iki client bir döngü içinde birbirini bağlantıdan atar; bu da sürekli kopan bir bağlantı gibi görünür. Rastgele ID'ler, sayfayı iki sekmede açtığınızda bunu önler.

Abone olma ve mesaj alma

message olayı gelen her PUBLISH için tetiklenir. payload bir bayt tamponudur; metin için toString(), JSON için JSON.parse(payload.toString()) çağırın. Üçüncü argüman retain, qos ve MQTT 5 altında properties alanlarını sunan ham pakettir.

log fonksiyonunda textContent kullanıldığına dikkat edin. Broker'ın public alanına herkes yayın yapabilir; bu yüzden her payload'ı güvenilmeyen girdi olarak ele alın. Onu innerHTML ile eklemek, kötü niyetli bir mesajın sayfanızda script çalıştırmasına izin verirdi.

Yayın yapma

client.publish(topic, payload, options, callback) mesajı kuyruğa alır. QoS 1 ile callback, broker mesajı PUBACK ile onayladıktan sonra çalışır. Bağlantı kopuksa MQTT.js, sayfa açık kaldığı sürece QoS 1 ve 2 mesajlarını giden deposunda tutar ve yeniden bağlandıktan sonra gönderir. QoS seviyeleri rehberi bu garantinin ne zaman önemli olduğunu açıklar.

Diğer Taraftan Test Etmek

Mesajların gerçekten broker'dan geçtiğini kanıtlamak için sayfada Publish'e tıklarken onları bir terminalden izleyin. Öneki sayfanızın gösterdiğiyle değiştirin:

mosquitto_sub -h broker.connectmq.com -p 1883 -i cli-watch-7f3a -t 'connectmq/demo/YOUR_PREFIX/#' -v

Terminalden yayın yapın, tarayıcı logu anında güncellenir:

mosquitto_pub -h broker.connectmq.com -p 1883 -i cli-pub-7f3a -t 'connectmq/demo/YOUR_PREFIX/sensors/room1' -m '{"temperature": 23.1}'

Tarayıcıdan TCP client'ına ve geri dönen bu gidiş-dönüş, bir WebSocket client'ı ile yerel bir TCP client'ının broker'da aynı topic alanını paylaştığının en açık kanıtıdır.

Sorun Giderme Kontrol Listesi

Durum hiçbir zaman "connected" olmuyorsa bu listeyi sırayla izleyin:

  1. Yanlış yol. ConnectMQ, WebSocket'i /mqtt yolunda sunar. Yolu olmayan bir URL HTTP yükseltmesi sırasında başarısız olur.
  2. Karma içerik. Bir https:// sayfası ws:// açamaz. 8084 portunda wss:// kullanın.
  3. Port engellenmiş. Bazı kurumsal ağlar yalnızca 443'e izin verir. Bunu elemek için başka bir ağdan veya telefonunuzun hotspot'undan test edin.
  4. Yinelenen client ID. Log'da connect ve close birkaç saniyede bir tekrarlanıyorsa başka bir client aynı ID'yi kullanıyor demektir.
  5. Boş veya geçersiz kimlik bilgileri. Private bir broker'da hatalı bir kullanıcı adı veya parola "Not authorized" ya da "Bad username or password" içeren bir error olayı üretir. Portaldaki değerleri kontrol edin.
  6. Public broker sınırları. Public broker client başına saniyede 10 mesaja, client başına 10 aboneliğe, mesaj başına 64 KB'a ve 8 topic seviyesine izin verir. Hızlı bir döngüye bağlanmış bir düğme hız sınırına takılır.
  7. DevTools. Network sekmesini açın, WS'ye göre filtreleyin ve çerçeveleri inceleyin. İkili MQTT paketlerini ve yükseltme yanıt kodunu görürsünüz.

Public Broker'dan Private Bir Broker'a Geçiş

Public broker bu eğitim için mükemmeldir, ancak public alanındaki her topic, onu tahmin eden herkes tarafından okunabilir. Gerçek projeler için kendi broker'ınızı oluşturun:

  1. app.connectmq.com adresinden kaydolun ve ücretsiz Serverless planını seçin.
  2. Bir broker oluşturun ve üretilen kullanıcı adını, parolayı ve client ID'yi kopyalayın.
  3. URL'yi broker'ınızın 8084 portundaki /mqtt yollu güvenli WebSocket uç noktasıyla değiştirin ve seçeneklerde username, password ve clientId değerlerini ayarlayın.

Bu kimlik bilgilerinin nerede durduğuna dikkat edin. Tarayıcı JavaScript'ine koyduğunuz her şey DevTools'u açan herkes tarafından okunabilir. İyi modeller şunlardır:

  • Tarayıcı panoları için cihazlarınızın kullandıklarını değil, ayrı ve düşük yetkili kimlik bilgileri kullanın.
  • Kimlik bilgilerini sayfaya gömmek yerine kullanıcıdan çalışma zamanında girmesini isteyin.
  • Herkese açık siteler için yetki gerektiren yayınları bir backend'e bırakın ve tarayıcıyı salt okunur tutun. Next.js MQTT modelleri yazısı bu ayrımı gösterir.

MQTT güvenliği için en iyi uygulamalar rehberi kimlik bilgisi yönetimi ve topic tasarımı konularına daha derinlemesine girer.

Bundan Sonra Ne Yapmalı?

Bu tek sayfa, birkaç yönde büyütebileceğiniz bir temeldir:

  • Canlı grafikler. JSON payload'larını ayrıştırın ve değerleri bir grafik kütüphanesine gönderin. Uzun oturumlarda belleğin sabit kalması için sabit uzunlukta bir dizi tutun.
  • Sohbet ve çevrimiçi durumu. Retained message'lar ve Last Will, kimin çevrimiçi olduğunu göstermeyi kolaylaştırır. MQTT sohbet uygulaması eğitimi tam olarak bunu oluşturur.
  • Tipli kod. Sayfa büyürse TypeScript'e ve bir bundler'a geçin; TypeScript ile MQTT rehberi payload'ların ve olayların tiplendirilmesini ele alır.
  • Diğer diller. Backend'iniz farklı bir teknoloji yığını kullanıyorsa MQTT client kütüphanelerine genel bakış MQTT.js'i Python, Go, Java ve C# client'larıyla karşılaştırır.

ConnectMQ ile Başlayın

ConnectMQ, 8084 portunda güvenli WebSocket'i önceden yapılandırılmış, Let's Encrypt sertifikalı ve sayfanızın ne yayınladığını kontrol etmek için portalda tarayıcı içi bir MQTT client'ı ile canlı topic gezgini sunan, tamamen yönetilen bir MQTT broker sağlar. Bugün public MQTT test broker ile başlayın, hazır olduğunuzda private bir bulut MQTT broker oluşturun. Kredi kartı gerektirmeyen Serverless planında ücretsiz bir hesap oluşturun.

Sık Sorulan Sorular

Bir tarayıcı 1883 portunda MQTT'ye bağlanabilir mi?

Hayır. Tarayıcılar ham TCP bağlantıları açamaz, bu yüzden WebSocket üzerinden MQTT kullanmaları gerekir. ConnectMQ'da bu, her ikisi de /mqtt yolunda olmak üzere ws:// için 8083, wss:// için 8084 portudur.

Tarayıcıda MQTT kullanmak için bir backend'e veya proxy'ye ihtiyacım var mı?

Hayır. Sayfa broker'a doğrudan WebSocket üzerinden bağlanır ve WebSocket CORS preflight'a tabi değildir. Bir backend yalnızca yetkili kimlik bilgilerini client'tan uzak tutmak istediğinizde faydalıdır.

Tarayıcılar için tek JavaScript MQTT kütüphanesi MQTT.js mi?

MQTT 5 desteği ve hazır bir tarayıcı paketiyle en yaygın kullanılan ve aktif olarak bakımı yapılan seçenektir. Eski Paho JavaScript client'ı hâlâ çalışır, ancak yeni projeler için artık yaygın tercih değildir.

Tarayıcı client'ım neden birkaç saniyede bir yeniden bağlanıyor?

En yaygın neden, aynı client ID'yi paylaşan iki client'tır; bu da broker'ın her seferinde eskisinin bağlantısını kesmesine yol açar. Sekme başına rastgele bir ID üretin ve public broker'ın hız sınırlarını aşmadığınızdan da emin olun.

İlgili yazılar

Test, Betik ve Hata Ayıklama için En İyi MQTT CLI Araçları

mosquitto_pub/sub, MQTTX CLI, HiveMQ MQTT CLI, MQTT.js CLI, curl ve mqttui'nin uygulamalı karşılaştırması; betik yazma ve hata ayıklama için doğru aracı seçebilmeniz için aynı test broker.connectmq.com üzerinde çalıştırıldı.

7 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.