Uygulamalı Eğitimler

Tarayıcıda Saf JavaScript ile MQTT (Build Adımı Olmadan)

MQTT.js 5'i CDN'den tek bir HTML dosyasına yükleyip güvenli WebSocket ile bağlanın: npm veya bundler olmadan publish, subscribe, yeniden bağlanma ve hata ayıklama.

Güncellendi · 8 dk okuma

Tarayıcıda Saf JavaScript ile MQTT (Build Adımı Olmadan)

Bir web sayfasından MQTT konuşmak için npm'e, React'e ya da bir bundler'a ihtiyacınız yok. MQTT.js 5, tarayıcıya hazır bir bundle ile gelir: Bir <script> etiketi ekleyin, mqtt.connect('wss://…') çağırın; sayfa güvenli WebSocket üzerinden publish ve subscribe yapar. Bu rehber, diskten açabileceğiniz, herhangi bir statik hosting'e koyabileceğiniz veya bir iç araca yapıştırabileceğiniz tek dosyalık eksiksiz bir istemci oluşturuyor.

Tarayıcılar neden WebSocket'e ihtiyaç duyar

Tarayıcılar ham TCP soketleri açamaz; bu yüzden mqtt://host:1883 ve mqtts://host:8883 bir web sayfasının erişemeyeceği adreslerdir. Broker'lar bunu bir WebSocket listener ile çözer: Aynı MQTT paketleri WebSocket frame'lerinin içinde taşınır. broker.connectmq.com için endpoint'ler şunlardır:

URLKullanım
ws://broker.connectmq.com:8083/mqttŞifresiz WebSocket; yalnızca http:// veya file:// ile açılan sayfalar için
wss://broker.connectmq.com:8084/mqttGüvenli WebSocket (TLS); her sayfadan çalışır, varsayılan olarak bunu kullanın

/mqtt yolu önemlidir: Doğru porta yanlış yolla bağlanmak genellikle HTTP upgrade sırasında başarısız olur (bkz. WebSocket yolu 404). WebSocket üzerinden MQTT bu taşıma katmanını ayrıntılı anlatır.

Sayfanın tamamı

Bunu index.html olarak kaydedin. Sayfa CDN'den MQTT.js'in tam bir sürümünü sabitler; bu dosya global bir mqtt nesnesi sunar.

index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>MQTT browser client</title>
  <script src="https://unpkg.com/mqtt@5.10.1/dist/mqtt.min.js"></script>
  <style>
    body { font: 15px/1.5 system-ui, sans-serif; max-width: 640px; margin: 2rem auto; padding: 0 1rem; }
    #log { background: #111; color: #9f9; padding: .75rem; height: 260px; overflow: auto; font-family: monospace; }
    input, button { font: inherit; padding: .4rem .6rem; }
  </style>
</head>
<body>
  <h1>MQTT over WSS</h1>
  <p>Status: <strong id="status">connecting…</strong></p>
  <form id="pub">
    <input id="msg" placeholder="Message" required>
    <button>Publish</button>
  </form>
  <pre id="log"></pre>

  <script>
    const URL = 'wss://broker.connectmq.com:8084/mqtt';
    const TOPIC = 'testmqtt/browser-demo/' + Math.random().toString(16).slice(2, 8);

    const $ = (id) => document.getElementById(id);
    const log = (line) => {
      $('log').textContent += new Date().toLocaleTimeString() + '  ' + line + '\n';
      $('log').scrollTop = $('log').scrollHeight;
    };

    const client = mqtt.connect(URL, {
      clientId: 'web-' + Math.random().toString(16).slice(2, 10),
      // username: 'username', password: 'password',   // see "Credentials" below
      protocolVersion: 5,
      clean: true,
      keepalive: 30,
      connectTimeout: 10_000,
      reconnectPeriod: 2_000,
    });

    client.on('connect', () => {
      $('status').textContent = 'connected';
      client.subscribe(TOPIC, { qos: 1 }, (err) => {
        log(err ? 'subscribe failed: ' + err.message : 'subscribed to ' + TOPIC);
      });
    });

    client.on('message', (topic, payload) => {
      log(topic + '  ' + payload.toString());
    });

    client.on('reconnect', () => { $('status').textContent = 'reconnecting…'; });
    client.on('offline',   () => { $('status').textContent = 'offline'; });
    client.on('error',     (err) => log('error: ' + err.message));

    $('pub').addEventListener('submit', (e) => {
      e.preventDefault();
      client.publish(TOPIC, $('msg').value, { qos: 1 });
      $('msg').value = '';
    });

    window.addEventListener('pagehide', () => client.end());
  </script>
</body>
</html>

Dosyayı açın, bir mesaj yazın ve Publish'e basın: Sayfa kendi rastgele topic'ine subscribe olduğu için mesaj broker üzerinden geri gelir ve log'da görünür. Her sekme kendi topic'ini ve client ID'sini alır, böylece açık iki sekme birbirini etkilemez. Trafiği dışarıdan görmek için online MQTT istemcisini açın, testmqtt/browser-demo/# topic'ine subscribe olun ve iki taraftan birinden publish edin.

ES modülü varyantı

Modülleri tercih ediyorsanız MQTT.js bir ESM build'i de yayınlar. Global değişken oluşturulmaz, bu yüzden import edersiniz:

Modül script'i
<script type="module">
  import mqtt from 'https://unpkg.com/mqtt@5.10.1/dist/mqtt.esm.js';

  const client = mqtt.connect('wss://broker.connectmq.com:8084/mqtt', { protocolVersion: 5 });
  client.on('connect', () => client.publish('testmqtt/browser-demo/esm', 'hello from a module'));
</script>

Modül script'leri otomatik olarak ertelenir ve window'a değişken sızdırmaz. Bazı tarayıcılar file:// ile açılan sayfalarda modül script'lerini engeller; bu yüzden klasörü yerel bir web sunucusuyla sunun:

Klasörü yerelde sunun
python3 -m http.server 8000
# ardından http://localhost:8000/ adresini açın

Tarayıcıda önemli olan seçenekler

SeçenekÖnerilenNeden
clientIdSekme başına rastgeleAynı ID'ye sahip iki sekme birbirini döngü halinde düşürür
protocolVersion5 (3.1.1 için 4)MQTT 5 hatalarda reason code verir, bu da hata ayıklamayı kolaylaştırır
keepalive30–60 snDizüstü bilgisayarlar uykuya geçer, Wi-Fi değişir; kısa bir keep-alive ölü soketleri daha erken fark eder
reconnectPeriod2.000–5.000 ms0 otomatik yeniden bağlanmayı kapatır; çok küçük değerler broker'ı yorar
connectTimeout10.000 msHızlıca başarısız olup kullanıcıya bir durum gösterin, sonsuza kadar yükleniyor demeyin
cleantrueBir tarayıcı sekmesi nadiren kalıcı session'a ihtiyaç duyar

Broker log'larında tanıyabileceğiniz bir önekle ID üretin veya client ID oluşturucuyu kullanın. Aynı kurulumu başka bir dilde istiyorsanız MQTT kod oluşturucu eşdeğer kod parçaları üretir.

Statik sayfada kimlik bilgileri

Bir HTML dosyasındaki her şey herkese açıktır: Herkes kaynak kodu görüntüleyip username ve password değerlerini kopyalayabilir. Tarayıcıdaki kimlik bilgilerine buna göre davranın:

  • Sayfaya özel bir broker kullanıcısı oluşturun ve ACL'lerle tam olarak ihtiyaç duyduğu topic'lerle sınırlayın. Bir dashboard çoğu zaman yalnızca .../telemetry/# üzerinde okuma iznine ihtiyaç duyar.
  • Tarayıcıda asla bir cihaz, backend veya yönetici hesabını yeniden kullanmayın.
  • Oturum açmış kullanıcılar için, kimlik doğrulamadan sonra backend'inizin kullanıcıya özel veya kısa ömürlü kimlik bilgileri üretmesini sağlayın ve bunları mqtt.connect'e verin.

Tarayıcıda MQTT WebSocket kimlik doğrulaması bu yaklaşımları ayrıntılı olarak ele alır.

Bağlantıda hata ayıklama

DevTools'u (F12) açın ve iki yere bakın:

  1. Console. error olayından gelen hatalar ve tarayıcının kendi WebSocket mesajları burada görünür.
  2. Network → WS. HTTP upgrade'i (başarılıysa 101 Switching Protocols durumu) ve Messages sekmesindeki ikili MQTT frame'lerini görmek için bağlantıyı seçin.
Konsol mesajıOlası nedenÇözüm
Mixed Content: The page at 'https://…' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://…'HTTPS sayfasından ws:// kullanılmışwss://…:8084/mqtt kullanın
WebSocket connection to 'wss://…' failedYanlış port veya yol, firewall, TLS sorunu8084 portunu ve /mqtt yolunu kontrol edin; bkz. WebSocket bağlantısı başarısız
connack timeoutWebSocket açıldı ama CONNACK zamanında gelmediBroker aşırı yüklü veya bir proxy veriyi tamponluyor; connectTimeout değerini artırıp tekrar deneyin
Connection refused: Not authorized / Bad User Name or PasswordEksik veya hatalı kimlik bilgileriKullanıcı adını, parolayı ve kullanıcının ACL'lerini kontrol edin
Durum bağlı ve yeniden bağlanıyor arasında gidip geliyorBaşka bir sekmede veya cihazda aynı client IDclientId'yi sekme başına benzersiz yapın

Reason code aracı, MQTT 5 broker'larının döndürdüğü sayısal kodları açıklar. Sayfanızı tamamen devre dışı bırakmak için aynı URL'yi online istemcide deneyin: Orada bağlanıyorsa sorun broker'da veya ağda değil, kodunuzdadır.

Demo sayfasının topic'ini online istemcide izleyin

Sonraki adımlar

Yukarıdaki sayfa eksiksiz bir istemcidir. Tipik sonraki adımlar bir sohbet arayüzü (oda başına bir topic, Last Will ile presence), sensör telemetrisiyle beslenen canlı bir grafik veya komut publish eden bir kontrol paneli olabilir. Kod birkaç yüz satırı geçtiğinde npm paketine ve bir bundler'a geçmek kolaydır: mqtt.connect API'si aynıdır; bu yüzden MQTT.js rehberi olduğu gibi geçerlidir.

Bir tarayıcının MQTT konuşması için bir script etiketi, bir wss:// URL'si ve birkaç olay işleyicisi yeterlidir. Kütüphane sürümünü sabitleyin, her sekmeye kendi client ID'sini verin, tarayıcıya yalnızca kısıtlı bir hesap gönderin ve yayına almadan önce her değişikliği DevTools'ta ve online istemcide doğrulayın.

Sıkça sorulan sorular

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

Hayır. Tarayıcılar ham TCP soketleri açamaz; bu yüzden bir web sayfası MQTT broker'ına yalnızca bir WebSocket listener üzerinden ulaşabilir. HTTPS ile sunulan her sayfadan wss:// kullanın (broker.connectmq.com'da 8084 portu ve /mqtt yolu).

MQTT kimlik bilgilerini statik bir HTML sayfasına koymak güvenli mi?

Sayfadaki her şeyi her ziyaretçi okuyabilir. ACL'i yalnızca o sayfanın ihtiyaç duyduğu topic'lere (çoğu zaman salt okuma) izin veren ayrı bir broker kullanıcısı kullanın ya da backend'inizin kısa ömürlü kimlik bilgileri vermesini sağlayın. Tarayıcıya asla yönetici veya cihaz hesabı göndermeyin.

Sayfam yerelde çalışıyor ama yayına alınca neden başarısız oluyor?

Genellikle mixed content yüzünden. https:// ile sunulan bir sayfa güvensiz bir ws:// bağlantısı açamaz, tarayıcı da bunu engeller. URL'yi TLS WebSocket portunda wss:// olarak değiştirin ve yolu kontrol edin.