Retained MQTT mesajlarıyla dijital ikiz oluşturmak, bir ikize bellek kazandırmanın en hafif yoludur: her özellik kendi retained topic'inde yaşar; böylece abone olan her görüntüleyici, veritabanı veya API olmadan eksiksiz güncel durumu anında alır. Bu eğitimde bir Python simülatörü, bağlandığında tam durumu yeniden oluşturan bir Node.js görüntüleyici ve retained topic'leri incelemek ve temizlemek için gereken komutlarla küçük bir makine ikizi oluşturacaksınız.
Daha geniş kavram için dijital ikiz teknolojisi rehberine bakın.
Retained Mesajlar Nasıl Çalışır
Normalde bir MQTT broker bir mesajı mevcut abonelere iletir ve unutur. Bir yayıncı retain bayrağını ayarladığında broker o mesajı ayrıca topic'in bilinen son değeri olarak saklar. Daha sonra eşleşen bir topic'e abone olan her istemci, saklanan mesajı retained olarak işaretlenmiş şekilde hemen alır.
Temel kurallar:
- Broker topic başına bir retained mesaj tutar: en yenisi öncekinin yerini alır.
- Wildcard abonelikler, eşleşen her topic'in retained mesajını alır.
- Retain bayrağıyla boş bir payload yayınlamak retained mesajı siler.
- Retained mesajlar, yayınlanan ve abone olunan QoS'tan düşük olanıyla iletilir.
Bu kombinasyon tam olarak bir ikizin ihtiyaç duyduğu şeydir: topic ile adreslenen ve wildcard ile okunabilen bir güncel durum anahtar-değer deposu. Bunun diğer durum yaklaşımları arasında nereye oturduğuna genel bir bakış için dijital ikiz mimarisi yazısına bakın.
Topic Ağacını Tasarlamak: Topic Başına Bir Özellik
Varlık başına bir JSON belgesi veya özellik başına bir değer retained tutabilirsiniz. Bu eğitim, gerçek avantajları olan özellik başına bir topic yaklaşımını kullanır:
| Yaklaşım | Artıları | Eksileri |
|---|---|---|
| Varlık başına bir retained JSON | Daha az mesaj, atomik anlık görüntü | Her değişiklik tüm alanları yeniden gönderir; eşzamanlı yazıcılar birbirinin üzerine yazar |
| Özellik başına bir retained topic | Küçük güncellemeler, bağımsız yazıcılar, tek bir değere kolay abonelik | Daha fazla topic; özellikler arasında atomik anlık görüntü yok |
Herkese açık broker üzerindeki bir CNC makinesi için ağaç şöyle görünür (8 topic seviyesinin içinde kalın):
connectmq/demo/f0c3/cell1/cnc1/spindle_rpm
connectmq/demo/f0c3/cell1/cnc1/feed_mm_min
connectmq/demo/f0c3/cell1/cnc1/tool
connectmq/demo/f0c3/cell1/cnc1/mode
connectmq/demo/f0c3/cell1/cnc1/alarm
connectmq/demo/f0c3/cell1/cnc1/status
Payload'lar düz değerlerdir, isteğe bağlı olarak bir zaman damgası içerir. Burada görüntüleyicilerin her değerin ne kadar taze olduğunu bilmesi için küçük bir JSON nesnesi {"v": 8000, "ts": 1792152000000} kullanıyoruz.
f0c3 değerini kendi rastgele metninizle değiştirin. Herkese açık MQTT test broker'ını herkes okuyabilir, bu yüzden yalnızca demo verisi yayınlayın.
Adım 1: İkiz Özelliklerini Retained Mesajlar Olarak Yayınlayın
Bu Python simülatörü her özelliği yalnızca değiştiğinde, her zaman retain=True ile yayınlar ve makineyi çevrimdışı işaretlemek için bir Last Will kullanır:
import json
import random
import time
import paho.mqtt.client as mqtt
BASE = "connectmq/demo/f0c3/cell1/cnc1"
last_sent = {}
def publish_property(client, name, value):
if last_sent.get(name) == value:
return
payload = json.dumps({"v": value, "ts": int(time.time() * 1000)})
client.publish(f"{BASE}/{name}", payload, qos=1, retain=True)
last_sent[name] = value
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="cnc1-twin-f0c3")
client.will_set(f"{BASE}/status", json.dumps({"v": "offline"}), qos=1, retain=True)
client.connect("broker.connectmq.com", 1883)
client.loop_start()
publish_property(client, "status", "online")
publish_property(client, "tool", 3)
try:
while True:
running = random.random() > 0.1
publish_property(client, "mode", "AUTO" if running else "HOLD")
publish_property(client, "spindle_rpm", random.choice([7950, 8000, 8050]) if running else 0)
publish_property(client, "feed_mm_min", 1000 if running else 0)
publish_property(client, "alarm", None if running else "E-STOP")
time.sleep(2)
except KeyboardInterrupt:
publish_property(client, "status", "offline")
time.sleep(0.5)
client.loop_stop()
client.disconnect()
Bir zamanlayıcıya göre değil, değişiklik olduğunda yayınlamak trafiği düşük tutar ve herkese açık broker'ın istemci başına saniyede 10 mesajlık hız sınırına uyar. Retained durum, görüntüleyicilerin değişmeyen değerleri yine de görmesini garanti eder.
Adım 2: Tam Durumu Anında Yükleyen Bir Görüntüleyici Oluşturun
Görüntüleyici bir wildcard ile abone olur, retained mesajları bir ikiz nesnesinde toplar ve ardından canlı güncellemeleri uygulamaya devam eder. Node.js'te MQTT.js ile:
const mqtt = require("mqtt");
const base = "connectmq/demo/f0c3/cell1/cnc1";
const twin = {};
const client = mqtt.connect("mqtt://broker.connectmq.com:1883", {
clientId: "cnc1-viewer-" + Math.random().toString(16).slice(2, 10),
protocolVersion: 5,
});
client.on("connect", () => {
client.subscribe(`${base}/+`, { qos: 1 });
});
client.on("message", (topic, payload, packet) => {
const property = topic.slice(base.length + 1);
if (payload.length === 0) {
delete twin[property];
return;
}
const { v, ts } = JSON.parse(payload.toString());
twin[property] = { value: v, ts, fromRetained: packet.retain };
console.clear();
console.table(twin);
});
Görüntüleyiciyi simülatör başladıktan sonra çalıştırın. Tablo tüm özelliklerle bir anda dolar, çünkü her retained mesaj abonelik anında packet.retain true olarak ayarlanmış şekilde iletilir. Sonraki güncellemeler canlı mesajlar olarak gelir. Tarayıcıda aynı kod wss://broker.connectmq.com:8084/mqtt ile çalışır; 3D ikiz görüntüleyicileri bütün bir sahneyi tek bir gidiş-dönüşte bu şekilde yükler. MQTT ile dijital ikiz yazısı tarayıcı varyantını gösterir.
Adım 3: Retained Topic'leri İnceleyin ve Temizleyin
Retained mesajlar değiştirilene veya temizlenene kadar kalır; bu, bir özelliği yeniden adlandırana kadar bir avantajdır. Önekinizin altındaki her şeyi inceleyin:
mosquitto_sub -h broker.connectmq.com -p 1883 -i inspect-f0c3 \
-t "connectmq/demo/f0c3/#" -v
Artık kullanmadığınız bir özelliği boş bir retained mesaj yayınlayarak temizleyin:
mosquitto_pub -h broker.connectmq.com -p 1883 -i cleanup-f0c3 \
-t "connectmq/demo/f0c3/cell1/cnc1/alarm" -r -n
-n bayrağı null (sıfır uzunlukta) bir payload gönderir; -r ile birlikte retained mesajı kaldırır.
Kalıbı Çok Sayıda Varlığa Ölçeklemek
Tek bir makine kolaydır; bütün bir tesis birkaç ek kural gerektirir. Aynı türdeki varlıklarda aynı özellik adlarını kullanın; böylece bir görüntüleyici herhangi bir CNC'yi aynı şablondan çizebilir. Varlık hiyerarşisini topic yoluna koyun, örneğin site/area/line/asset/property; böylece görüntüleyiciler tam olarak gösterdikleri dala abone olabilir: bir hat görünümü .../line2/+/+ adresine, tek bir makine sayfası .../line2/cnc4/+ adresine abone olur. Herkese açık broker'da 8 topic seviyesi ve istemci başına 10 abonelik sınırını unutmayın; bu bir demo için fazlasıyla yeterlidir, ancak gerçek kurulumlar için kendi broker'ınızı kullanmanız için bir nedendir.
Büyük bir dalı açan görüntüleyiciler, özellik başına bir retained mesajı aynı anda alır. Bu genellikle sorun değildir; ancak sahneyi her mesaj için yeniden çizmek yerine, ilk render'dan önce mesajları toplu halde ayrıştırıp uygulayın. Sonuç, ilk karede eksiksiz görünen bir ikizdir.
Retained İkizleri İyileştiren MQTT 5 Seçenekleri
MQTT 5, retained durumu daha hassas hale getiren kontroller ekler:
- Message expiry interval: değişken özelliklere bir süre sonu ayarlayın; böylece yenilenmeyen retained bir değer, bayat bir okumayı sonsuza kadar göstermek yerine kaybolur.
- Abonelikte retain handling:
0her abonelikte retained mesajları gönderir,1yalnızca yeni aboneliklerde,2hiçbir zaman. Yalnızca canlı değişiklikleri isteyen tüketiciler için2kullanın. - Retain as published: bir köprünün veya aktarıcının orijinal mesajın retained olup olmadığını görmesini sağlar.
MQTT.js'te { qos: 1, rh: 2 } ile yapılan bir abonelik retained mesajları atlar; { retain: true, properties: { messageExpiryInterval: 300 } } ile yayınlamak ise bir değerin beş dakika sonra sona ermesini sağlar. Daha fazlası için MQTT 5 özellikleri yazısına bakın.
Tuzaklar ve Sorun Giderme
- Hayalet özellikler: yeniden adlandırılan topic'ler eski retained değerleri geride bırakır. Bunları açıkça temizleyin.
- Retained komutlar: komut topic'lerini asla retained yapmayın; cihazlar yeniden bağlandığında onları tekrar çalıştırır.
- Canlıymış gibi gösterilen bayat değerler: zaman damgaları ekleyin ve durum topic'ine uyun.
- Aşırı büyük retained payload'lar: her değeri küçük tutun; herkese açık broker mesaj başına 64 KB'a, ücretsiz Serverless plan 256 KB'a kadar kabul eder.
- Atomik anlık görüntü yok: birkaç özelliğin birlikte değişmesi gerekiyorsa, bunları tek bir retained JSON belgesi olarak yayınlayın.
- Broker yeniden başlatmaları: retained durumun broker yeniden başlatmalarından sonsuza kadar sağ çıkacağını varsaymak yerine, cihazların yeniden bağlandığında durumu yeniden yayınlamasını planlayın. Bağlantıda tam durumu yayınlayan cihazlar ikizi kendi kendini onaran bir yapıya kavuşturur.
Retained Topic'ler Ne Zaman Yetmez
Retained topic'ler güncel durum için idealdir. Geçmişe (bir zaman serisi abonesi), varlıklar arası sorgulara veya ikiz başına erişim kontrolüne (MQTT ile Eclipse Ditto gibi bir ikiz servisi) ya da ölçekte istenen ve bildirilen durum yönetimine ihtiyaç duyduğunuzda başka bileşenler ekleyin. Retained topic'ler üzerinde istenen/bildirilen kalıbı için dijital ikiz durum senkronizasyonu yazısını okuyun.
Retained Durumlu İkizinizi ConnectMQ Üzerinde Çalıştırın
Gerçek varlıklar için herkese açık broker'dan, MQTT 3.1.1 ve 5.0, retained mesajlar, message expiry ve TLS sunan yönetilen bir MQTT broker olan ConnectMQ üzerindeki özel bir broker'a geçin. Host'u kendi broker'ınızla değiştirin, portaldan aldığınız YOUR_USERNAME, YOUR_PASSWORD ve YOUR_CLIENT_ID değerlerini ekleyin ve 8883 portuna ya da tarayıcılar için 8084'e geçin. Kredi kartı gerekmeden ücretsiz Serverless planla app.connectmq.com adresinden kaydolun ve ikizinizin retained topic'lerini canlı topic gezgininde izleyin.
Sık Sorulan Sorular
MQTT'de retained mesaj nedir?
Broker'ın topic'inin bilinen son değeri olarak sakladığı ve o topic'e yeni abone olan herkese hemen ilettiği bir mesajdır.
Retained bir MQTT mesajını nasıl silerim?
Aynı topic'e retain bayrağıyla sıfır uzunlukta bir payload yayınlayın; örneğin mosquitto_pub -t <topic> -r -n.
Her ikiz özelliğinin kendi retained topic'i olmalı mı?
Bağımsız özellikler ve küçük güncellemeler için iyi çalışır. Birkaç değerin atomik olarak birlikte değişmesi gerektiğinde varlık başına bir retained JSON belgesi kullanın.
Retained mesajlar bir dijital ikiz için veritabanının yerini alabilir mi?
Güncel durum için çoğu zaman evet. Geçmiş, varlıklar arası sorgular veya denetim izleri için broker'ın yanına bir veritabanı abonesi ekleyin.



