Raspberry Pi

WebSocket Üzerinden Canlı MQTT Verisi İçin Raspberry Pi Kiosk Paneli

Bir Raspberry Pi'yi ve herhangi bir HDMI ekranı duvara monte bir panele dönüştürün. Tek bir HTML sayfası güvenli WebSocket üzerinden MQTT'ye abone olur ve Chromium her açılışta kiosk modunda tam ekran başlar.

Canlı MQTT sıcaklık ve makine durumu kutucuklarını gösteren raspberry pi kiosk paneliyle çalışan duvara monte ekran
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

Bir Raspberry Pi kiosk paneli, ucuz bir kartı ve herhangi bir HDMI monitörü klavye, fare veya oturum açma gerektirmeden canlı sensör değerlerini gösteren bir duvar ekranına dönüştürür. Bu eğitimde güvenli WebSocket üzerinden MQTT'ye abone olan tek dosyalık bir HTML paneli yazacak, onu Pi'den sunacak ve Chromium'u ekran kararması devre dışı bırakılmış şekilde açılışta tam ekran başlayacak biçimde yapılandıracaksınız. Sonuç elektrik kesintilerini atlatır ve ara sıra yapılan işletim sistemi güncellemeleri dışında bakım gerektirmez.

Kiosk Verilerini Nereden Alıyor

Pi üzerindeki tarayıcı WebSocket üzerinden doğrudan MQTT broker'a bağlanır. Arka uç sunucusu, veritabanı veya yoklama (polling) yoktur. Bir sensör yayın yaptığında broker mesajı kiosk sayfası dahil her aboneye iter ve ekrandaki değer birkaç an içinde değişir.

Bu tasarım, broker'ın WebSocket üzerinden MQTT sunmasına bağlıdır, çünkü tarayıcılar ham TCP soketleri açamaz. broker.connectmq.com adresindeki genel MQTT test broker'ı TLS ile 8084 portunda (wss://, yol /mqtt) ve TLS olmadan 8083 portunda dinler. Her zaman güvenli portu kullanın: Chromium, HTTPS üzerinden sunulan sayfalardan gelen güvensiz WebSocket bağlantılarını engeller ve şifrelemenin burada fark edilir bir maliyeti yoktur. WebSocket üzerinden MQTT rehberi protokol ayrıntılarını açıklar.

Retained mesajlar kiosku anında açılıyormuş gibi hissettirir. Sensörler en son durumlarını retain bayrağıyla yayınlarsa, broker bu değerleri sayfa abone olduğu anda ona verir; böylece ekran bir sonraki okumayı beklemek yerine açılıştan bir saniye sonra tamamen dolar.

Parça Ne yapar Nerede çalışır
Sensörler JSON yayınlar, ideal olarak retained İnterneti olan her yerde
MQTT broker Mesajları yönlendirir, retained değerleri saklar Bulut
dashboard.html WSS üzerinden abone olur, kutucukları çizer Pi üzerindeki Chromium
Yerel web sunucusu HTML dosyasını sunar Pi, port 8080
Chromium kiosk Tam ekran tarayıcı, arayüz yok Pi masaüstü oturumu

Neye İhtiyacınız Var

  • Masaüstlü Raspberry Pi OS (Bookworm) yüklü Raspberry Pi 4 veya 5 (basit sayfalar için Pi 3B+ de çalışır).
  • HDMI üzerinden bir monitör veya TV ya da resmi dokunmatik ekran.
  • 8084 portuna dışa doğru erişimi olan Wi-Fi veya Ethernet.
  • MQTT verisi yayınlayan bir şey. Hızlı bir başlangıç için Raspberry Pi sistem istatistikleri yayıncısı herhangi bir Pi'den gerçek değerler üretir.

Güncel Bookworm imajları bir Wayland masaüstü çalıştırır (güncel sürümlerde labwc, önceki Bookworm sürümlerinde Wayfire). Aşağıdaki otomatik başlatma adımları labwc'yi kapsar ve alternatifi belirtir.

Adım 1: Panel Sayfasını Yazın

Bir klasör ve sayfayı oluşturun:

mkdir -p ~/kiosk && nano ~/kiosk/dashboard.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Site Dashboard</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
  :root { color-scheme: dark; }
  body { margin: 0; font-family: system-ui, sans-serif; background: #0f1419; color: #e6e6e6; }
  header { display: flex; justify-content: space-between; padding: 16px 28px; font-size: 22px; }
  #status.ok { color: #4caf50; } #status.bad { color: #f44336; }
  main { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; padding: 0 28px 28px; }
  .tile { background: #1b2229; border-radius: 12px; padding: 24px; }
  .label { font-size: 20px; opacity: .7; }
  .value { font-size: 72px; font-weight: 600; margin-top: 8px; }
  .age { font-size: 16px; opacity: .5; margin-top: 6px; }
  .stale .value { opacity: .35; }
</style>
</head>
<body>
<header><span>Site Dashboard</span><span id="clock"></span><span id="status" class="bad">offline</span></header>
<main id="tiles"></main>
<script src="https://unpkg.com/mqtt@5.10.1/dist/mqtt.min.js"></script>
<script>
  const PREFIX = "connectmq/demo/c81f3d";
  const TILES = [
    { topic: PREFIX + "/office/climate",  field: "t",    label: "Office temperature", unit: " °C" },
    { topic: PREFIX + "/office/climate",  field: "rh",   label: "Office humidity",    unit: " %"  },
    { topic: PREFIX + "/pi01/stats",      field: "cpu_temp", label: "Gateway CPU",    unit: " °C" },
    { topic: PREFIX + "/line1/state",     field: null,   label: "Line 1",             unit: ""    }
  ];
  const STALE_MS = 5 * 60 * 1000;

  const tilesEl = document.getElementById("tiles");
  const lastSeen = new Map();
  TILES.forEach((t, i) => {
    const el = document.createElement("div");
    el.className = "tile stale"; el.id = "tile" + i;
    el.innerHTML = '<div class="label"></div><div class="value">--</div><div class="age">waiting</div>';
    el.querySelector(".label").textContent = t.label;
    tilesEl.appendChild(el);
  });

  const client = mqtt.connect("wss://broker.connectmq.com:8084/mqtt", {
    clientId: "kiosk-c81f3d-" + Math.random().toString(16).slice(2, 8),
    protocolVersion: 5,
    clean: true,
    reconnectPeriod: 5000,
    connectTimeout: 10000
    // Private broker: add username: "YOUR_USERNAME", password: "YOUR_PASSWORD"
    // and use clientId: "YOUR_CLIENT_ID"
  });

  const statusEl = document.getElementById("status");
  client.on("connect", () => {
    statusEl.textContent = "live"; statusEl.className = "ok";
    const topics = [...new Set(TILES.map(t => t.topic))];
    client.subscribe(topics, { qos: 1 });
  });
  client.on("close", () => { statusEl.textContent = "reconnecting"; statusEl.className = "bad"; });

  client.on("message", (topic, payload) => {
    const text = payload.toString();
    let data = null;
    try { data = JSON.parse(text); } catch (e) { /* plain string payload */ }
    TILES.forEach((t, i) => {
      if (t.topic !== topic) return;
      let v = t.field ? (data ? data[t.field] : undefined) : text;
      if (v === undefined || v === null) return;
      if (typeof v === "number") v = v.toFixed(1);
      const el = document.getElementById("tile" + i);
      el.querySelector(".value").textContent = v + t.unit;
      el.classList.remove("stale");
      lastSeen.set(i, Date.now());
    });
  });

  setInterval(() => {
    document.getElementById("clock").textContent = new Date().toLocaleTimeString();
    TILES.forEach((t, i) => {
      const seen = lastSeen.get(i);
      const el = document.getElementById("tile" + i);
      if (!seen) return;
      const age = Math.round((Date.now() - seen) / 1000);
      el.querySelector(".age").textContent = age < 60 ? "updated " + age + " s ago" : "updated " + Math.round(age / 60) + " min ago";
      el.classList.toggle("stale", Date.now() - seen > STALE_MS);
    });
  }, 1000);
</script>
</body>
</html>

Sayfa, başında kimsenin olmadığı bir ekranda önemli olan üç şey yapar. Yanından geçen herkesin sayıların canlı olup olmadığını bilmesi için bir bağlantı göstergesi gösterir. Beş dakika içinde güncellenmeyen kutucukları soluklaştırır; bu da ölü bir sensörün eski bir değeri sessizce güncelmiş gibi göstermesini önler. Ve ağ koptuğunda her beş saniyede bir kendiliğinden yeniden bağlanır.

MQTT.js'yi her açılışta bir CDN'den yüklemek istemiyorsanız, dosyayı bir kez ~/kiosk/ klasörüne indirin ve src değerini mqtt.min.js olarak değiştirin. Böylece kiosk internete yalnızca broker bağlantısının kendisi için ihtiyaç duyar.

Adım 2: Sayfayı Yerel Olarak Sunun

Chromium file:// URL'lerini açabilir, ancak Pi'den HTTP üzerinden sunmak tuhaf tarayıcı kısıtlamalarından kaçınmanızı sağlar. Python'un yerleşik sunucusu yeterlidir. Açılışta başlaması için bir systemd servisi oluşturun:

sudo tee /etc/systemd/system/kiosk-web.service >/dev/null <<'EOF'
[Unit]
Description=Kiosk dashboard web server
After=network-online.target
Wants=network-online.target

[Service]
User=pi
WorkingDirectory=/home/pi/kiosk
ExecStart=/usr/bin/python3 -m http.server 8080 --bind 127.0.0.1
Restart=always

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now kiosk-web

Kullanıcı adınız farklıysa pi yerine onu yazın. 127.0.0.1 adresine bağlamak, sayfayı yalnızca Pi'nin kendisine özel tutar.

Adım 3: Chromium'u Raspberry Pi Kiosk Modunda Başlatın

Önce Pi'nin otomatik oturum açmayla doğrudan masaüstüne açıldığından emin olun: sudo raspi-config çalıştırın, System Options, Boot / Auto Login bölümünü açın ve Desktop Autologin seçeneğini seçin. Oradayken Display Options, Screen Blanking bölümünü açıp ekran kararmasını devre dışı bırakın.

Küçük bir başlatıcı betik oluşturun:

nano ~/kiosk/start-kiosk.sh
#!/bin/bash
# Wait for the local web server and network
for i in $(seq 1 30); do
  curl -s -o /dev/null http://127.0.0.1:8080/dashboard.html && break
  sleep 2
done

BROWSER=$(command -v chromium-browser || command -v chromium)
exec "$BROWSER" \
  --kiosk \
  --noerrdialogs \
  --disable-infobars \
  --disable-session-crashed-bubble \
  --check-for-update-interval=31536000 \
  --ozone-platform=wayland \
  http://127.0.0.1:8080/dashboard.html
chmod +x ~/kiosk/start-kiosk.sh

labwc kullanıyorsanız başlatıcıyı compositor'ün autostart dosyasına ekleyin:

mkdir -p ~/.config/labwc
echo "/home/pi/kiosk/start-kiosk.sh &" >> ~/.config/labwc/autostart

Wayfire çalıştıran eski bir Bookworm sürümündeyseniz bunun yerine şunu ~/.config/wayfire.ini dosyasına ekleyin:

[autostart]
kiosk = /home/pi/kiosk/start-kiosk.sh

Pi'yi raspi-config'de yeniden X11'e geçirdiyseniz --ozone-platform=wayland bayrağını kaldırın ve betiği gösteren bir Exec= satırıyla ~/.config/autostart/kiosk.desktop dosyasını kullanın. Yeniden başlatın; panel ekranı doldurmalıdır.

Başında Kimse Olmayan Bir Raspberry Pi Kiosk Panelini Sağlamlaştırma

Bir kiosk aylarca kimse ona bakmadan çalışır; bu yüzden sıkıcı arızalara karşı plan yapın:

  1. Çökmeler. --disable-session-crashed-bubble bayrağı, elektrik kesintisinden sonra çıkan "sayfaları geri yükle" çubuğunu engeller. Ek güvenlik için exec komutunu bir döngüye sarın; böylece Chromium kapanırsa yeniden başlar.
  2. Bellek şişmesi. Uzun süre çalışan tarayıcı sekmeleri büyüyebilir. sudo crontab -e ile 0 4 * * * /sbin/reboot satırını ekleyerek her gece yeniden başlatmak kaba ama güvenilir bir çözümdür.
  3. SD kart yıpranması. Chromium sürekli olarak bir profil yazar. Kurulum son haline geldiğinde raspi-config'de overlay dosya sistemini etkinleştirmeyi düşünün; bu, kök dosya sistemini salt okunur yapar.
  4. Ekran yanması. OLED veya plazma ekranlardaki sabit düzenler hayalet görüntüler bırakabilir. Koyu arka planlar kullanın ve zamanlanmış bir betikle wlr-randr --output HDMI-A-1 --off çalıştırarak ekranı geceleri kapatın.
  5. Ekrandaki kimlik bilgileri. Sayfa kaynağındaki her şey fiziksel erişimi olan herkes tarafından görülebilir. Kiosk için kendi kimlik bilgilerine sahip özel bir istemci kullanın.

Üretim: Kiosk İçin Özel Bir Broker

Genel test broker'ı geliştirme aşamasında idealdir, ancak oradaki topic'leri herkes okuyup yazabilir; bu yüzden gerçek bir duvar ekranı kendi broker'ınıza abone olmalıdır. ConnectMQ gibi tamamen yönetilen bir MQTT hizmeti, WebSocket ve güvenli WebSocket'in kutudan çıktığı gibi etkin olduğu özel bir broker sunar. Portalda bir broker oluşturur ve bir kullanıcı adı, parola ve client ID alırsınız; bunları mqtt.connect seçeneklerine koyun ve verilen client ID'yi aynen kullanın, çünkü ConnectMQ client ID'leri kimlik bilgilerine bağlar. Sayfa yalnızca tek bir bağlantı kullandığından, sensörlerinizle birlikte ücretsiz Serverless plana rahatça sığar.

Her şeyi kiosk'a bağlamadan önce, ConnectMQ portalının tarayıcı içi MQTT istemcisi ve canlı topic gezgini, sensörlerin kutucuklarınızın beklediği topic'leri ve JSON alanlarını yayınladığını kontrol etmek için kullanışlıdır.

Sorun Giderme

Belirti Neden Çözüm
Durum "offline" olarak kalıyor 8084 portu engelli veya yol yanlış wss://...:8084/mqtt kullanın ve güvenlik duvarını kontrol edin
Kutucuklar sürekli -- gösteriyor Topic veya alan uyuşmazlığı mosquitto_sub -v ile abone olup karşılaştırın
Değerler ancak dakikalar sonra görünüyor Sensörler retain kullanmıyor En son değeri retain bayrağıyla yayınlayın
Açılıştan sonra siyah ekran Autostart dosyası okunmuyor Hangi compositor'ün çalıştığını echo $XDG_SESSION_DESKTOP ile kontrol edin
Ekran 10 dakika sonra kapanıyor Kararma etkin raspi-config, Display Options bölümünden devre dışı bırakın

ConnectMQ ile Başlayın

Kiosk'unuza özel, TLS ile korunan bir veri akışı sağlayın: app.connectmq.com adresinde kredi kartı gerekmeden ücretsiz Serverless planda bir broker oluşturun ve kimlik bilgilerini dashboard.html dosyasına yapıştırın. Komut da gönderebilen bir dokunmatik ekran sürümü oluşturmak için Raspberry Pi MQTT ekran eğitimi ile devam edin veya Raspberry Pi MQTT eğitimi ile temellere dönün.

Sık Sorulan Sorular

Kiosk'um neden 1883 portu yerine WebSocket üzerinden MQTT'ye ihtiyaç duyuyor?

Tarayıcılar ham TCP soketleri değil, yalnızca HTTP ve WebSocket bağlantıları açabilir; bu yüzden bir web sayfası 1883 portunu doğrudan kullanamaz. 8084 portundaki güvenli WebSocket, tarayıcıdan abone olmanın standart yoludur.

Özel bir HTML sayfası yerine Grafana kullanabilir miyim?

Evet, bir Grafana panel URL'sini aynı şekilde kiosk modunda açın. Özel bir sayfa daha hafiftir ve anında güncellenir; geçmişe ve grafiklere ihtiyaç duyduğunuzda ise Grafana daha iyidir.

Chromium kiosk modundan nasıl çıkarım?

Bir klavye bağlayıp Alt+F4'e basın veya Pi'ye SSH ile bağlanıp pkill chromium çalıştırın. Normal masaüstünü geri istiyorsanız autostart satırını kaldırın.

İnternet kesilirse kiosk çalışmaya devam eder mi?

Sayfa ekranda kalır, kendini yeniden bağlanıyor olarak işaretler ve eskiyen kutucukları soluklaştırır. Bağlantı geri geldiğinde MQTT.js yeniden bağlanır ve retained değerler ekranı yeniler.

İlgili yazılar

RC522 Okuyucu ile Raspberry Pi RFID MQTT Erişim Kaydı

Bir RC522 RFID okuyucuyu Raspberry Pi'ye bağlayın, etiketleri Python ile okuyun, yerel bir izin listesiyle karşılaştırın ve her erişim denemesini kayıt araçlarının, panellerin ve uyarı araçlarının tüketebileceği bir MQTT olayı olarak yayınlayın.

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.