Sparkplug birth ve death sertifikaları, her tüketiciye bir edge node'un veya cihazın ne zaman çevrimiçi olduğunu, hangi metriklere sahip olduğunu ve ne zaman ortadan kaybolduğunu bildiren mesajlardır. Bu rehberde NBIRTH, NDEATH, DBIRTH ve DDEATH'in seq ve bdSeq sayaçlarıyla birlikte nasıl çalıştığını öğrenecek ve tüm yaşam döngüsünü canlı bir broker'a yayınlayan küçük bir Python edge node simülatörü çalıştıracaksınız.
Sparkplug Neden Birth ve Death Mesajlarına İhtiyaç Duyar?
Düz MQTT bir subscriber'a yalnızca bir değerin geldiğini söyler. Göndericinin hâlâ hayatta olup olmadığını, son değerin hâlâ geçerli olup olmadığını veya başka hangi değerlerin bulunduğunu söylemez. Bir tesiste bu gerçek bir sorundur: gateway on dakika önce çevrimdışı olmuşsa, bir pompanın 1.450 rpm'de çalıştığını gösteren operatör ekranı tehlikelidir.
Sparkplug bunu iki MQTT özelliği üzerine kurulu bir durum modeliyle çözer: last will and testament ve tek bir bağlantı üzerinde sıralı teslimat. Her edge node, tüm metriklerini ve güncel değerlerini listeleyen bir birth sertifikasıyla kendini duyurur. Bağlantısı ister düzgün ister beklenmedik şekilde kesilsin, bir death sertifikası herkese bu değerlerin artık bayat olduğunu bildirir. Host uygulamaları da eski sayıları canlıymış gibi göstermek yerine tag'leri kötü kaliteli olarak işaretleyebilir.
Dört Sertifika
| Mesaj | Yayınlayan | Ne zaman | İçerik |
|---|---|---|---|
| NBIRTH | Edge node | Bağlandıktan hemen sonra | Tüm node metrikleri, bdSeq, seq 0, Node Control metrikleri |
| NDEATH | Last will aracılığıyla broker veya node | Node oturumu sona erdiğinde | NBIRTH ile eşleşen bdSeq |
| DBIRTH | Edge node | NBIRTH'ten sonra, her cihaz için | Güncel değerleriyle tüm cihaz metrikleri |
| DDEATH | Edge node | Node'un arkasındaki bir cihaz kaybedildiğinde | Yalnızca sıra numarası |
Topic'ler Sparkplug topic namespace yapısını izler: node mesajları için spBv1.0/{group}/NBIRTH/{node}, cihazlar için spBv1.0/{group}/DBIRTH/{node}/{device}.
NBIRTH
Node birth, MQTT bağlantısı başarılı olduktan sonraki ilk mesajdır. Her node seviyesi metriği adı, veri tipi ve güncel değeriyle birlikte içermeli; ayrıca bir host'un yeni bir birth isteyebilmesi için bir bdSeq metriği ve bir Node Control/Rebirth boolean metriği barındırmalıdır. Metrik alias'ları kullanılıyorsa, adlar ile alias'lar NBIRTH'te eşleştirilir.
NDEATH
Node death, node bağlanırken MQTT will mesajı olarak kaydedilir; böylece TCP bağlantısı koparsa veya keepalive süresi dolarsa broker bunu otomatik olarak yayınlar. Düzgün şekilde kapanan bir node, bağlantıyı kesmeden önce bunu kendisi yayınlar. Retained değildir ve Sparkplug 3.0'da will QoS 1 kullanır.
DBIRTH ve DDEATH
Cihazların kendi MQTT bağlantıları yoktur, bu nedenle will kullanamazlar. Edge node, kendi NBIRTH'ünden sonra her cihaz için bir DBIRTH yayınlar ve bir cihazla iletişimi kaybettiğinde, örneğin bir Modbus zaman aşımında, bir DDEATH yayınlar. Node'un kendisi öldüğünde tüm cihazları da örtük olarak ölü kabul edilir; ayrı ayrı DDEATH mesajlarına gerek yoktur.
Sıra Numaraları: seq ve bdSeq
İki sayaç host uygulamalarını doğru yolda tutar.
seq, 0 ile 255 arasında bir payload alanıdır. NBIRTH her zaman seq 0'a sahiptir ve o node'dan gelen her sonraki mesaj (DBIRTH, NDATA, DDATA, DDEATH) bunu bir artırır; 255'ten sonra 0'a döner. Bir atlama gören host, bir mesajı kaçırdığını ve görünümünün yanlış olabileceğini anlar.
bdSeq (birth/death sırası) bir payload alanı değil, bir metriktir. Node her yeni MQTT oturumu başlattığında artar. Node, aynı bdSeq değerini hem bağlanırken kaydettiği NDEATH will'ine hem de bağlandıktan sonra yayınladığı NBIRTH'e koyar. Bir will gecikmeli teslim edilebildiği için, aksi takdirde host yeni bir NBIRTH'ten sonra eski bir NDEATH alıp canlı bir node'u yanlışlıkla çevrimdışı olarak işaretleyebilirdi. Eşleşen bdSeq değerleri, host'un önceki bir oturuma ait death mesajını yok saymasını sağlar.
Adım Adım Yaşam Döngüsü
- Edge node bdSeq'i artırır ve bunu içeren bir NDEATH payload'ı oluşturur.
- Clean session kullanarak, bu NDEATH'i will olarak (QoS 1, retained değil) ayarlayıp broker'a bağlanır.
- Rebirth ve yazma komutlarını alabilmek için NCMD ve DCMD topic'lerine abone olur.
- Bir primary host uygulamasını izleyecek şekilde yapılandırılmışsa, o host'un STATE mesajı çevrimiçi diyene kadar bekler.
- seq 0 ve aynı bdSeq ile NBIRTH yayınlar.
- Her cihaz için bir DBIRTH yayınlar.
- NDATA ve DDATA'yı değişiklik olduğunda (report by exception) yayınlar ve her seferinde seq'i artırır.
- Kapanırken NDEATH yayınlar; çökme durumunda broker will'i onun yerine yayınlar.
Python'da Bir Birth ve Death Simülatörü Çalıştırın
Aşağıdaki betik bu yaşam döngüsünü paho-mqtt 2.x ile uygular. Eclipse Tahu sparkplug_b.proto dosyasından üretilmiş Python sınıflarına ihtiyaç duyar. Proto dosyasını Tahu deposundan indirin ve sınıfları bir kez üretin:
pip install "paho-mqtt>=2.0" protobuf grpcio-tools
curl -O https://raw.githubusercontent.com/eclipse/tahu/master/sparkplug_b/sparkplug_b.proto
python -m grpc_tools.protoc -I. --python_out=. sparkplug_b.proto
Bu, proto dosyasının yanında sparkplug_b_pb2.py dosyasını oluşturur. Simülatörü aynı klasöre edge_sim.py olarak kaydedin:
import random
import time
import uuid
import paho.mqtt.client as mqtt
import sparkplug_b_pb2 as spb
BROKER = "broker.connectmq.com"
PORT = 1883
GROUP = "demo-" + uuid.uuid4().hex[:6] # herkese açık broker'da benzersiz grup
NODE = "line1"
DEVICE = "cnc1"
# Sparkplug veri tipi kodları
INT64, DOUBLE, BOOLEAN = 4, 10, 11
seq = 0
bd_seq = 0
def now_ms():
return int(time.time() * 1000)
def next_seq():
global seq
value = seq
seq = (seq + 1) % 256
return value
def add_metric(payload, name, datatype, value):
m = payload.metrics.add()
m.name = name
m.timestamp = now_ms()
m.datatype = datatype
if datatype == INT64:
m.long_value = value
elif datatype == DOUBLE:
m.double_value = value
elif datatype == BOOLEAN:
m.boolean_value = value
def topic(msg_type, device=None):
base = f"spBv1.0/{GROUP}/{msg_type}/{NODE}"
return f"{base}/{device}" if device else base
def ndeath_payload():
p = spb.Payload()
p.timestamp = now_ms()
add_metric(p, "bdSeq", INT64, bd_seq)
return p.SerializeToString()
def publish_births(client):
global seq
seq = 0
nbirth = spb.Payload(timestamp=now_ms(), seq=next_seq())
add_metric(nbirth, "bdSeq", INT64, bd_seq)
add_metric(nbirth, "Node Control/Rebirth", BOOLEAN, False)
add_metric(nbirth, "Properties/Uptime", INT64, 0)
client.publish(topic("NBIRTH"), nbirth.SerializeToString(), qos=0)
dbirth = spb.Payload(timestamp=now_ms(), seq=next_seq())
add_metric(dbirth, "Spindle/Speed", DOUBLE, 0.0)
add_metric(dbirth, "Spindle/Running", BOOLEAN, False)
client.publish(topic("DBIRTH", DEVICE), dbirth.SerializeToString(), qos=0)
print(f"births published for {GROUP}/{NODE}/{DEVICE} (bdSeq={bd_seq})")
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print("connect failed:", reason_code)
return
client.subscribe(f"spBv1.0/{GROUP}/NCMD/{NODE}", qos=0)
client.subscribe(f"spBv1.0/{GROUP}/DCMD/{NODE}/#", qos=0)
publish_births(client)
def on_message(client, userdata, msg):
cmd = spb.Payload()
cmd.ParseFromString(msg.payload)
for m in cmd.metrics:
if m.name == "Node Control/Rebirth" and m.boolean_value:
print("rebirth requested")
publish_births(client)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"edge-sim-{uuid.uuid4().hex[:8]}",
clean_session=True)
client.on_connect = on_connect
client.on_message = on_message
client.will_set(topic("NDEATH"), ndeath_payload(), qos=1, retain=False)
client.connect(BROKER, PORT, keepalive=30)
client.loop_start()
try:
while True:
time.sleep(2)
ddata = spb.Payload(timestamp=now_ms(), seq=next_seq())
add_metric(ddata, "Spindle/Speed", DOUBLE, round(random.uniform(1400, 1500), 1))
add_metric(ddata, "Spindle/Running", BOOLEAN, True)
client.publish(topic("DDATA", DEVICE), ddata.SerializeToString(), qos=0)
except KeyboardInterrupt:
ddeath = spb.Payload(timestamp=now_ms(), seq=next_seq())
client.publish(topic("DDEATH", DEVICE), ddeath.SerializeToString(), qos=0)
client.publish(topic("NDEATH"), ndeath_payload(), qos=1).wait_for_publish()
client.disconnect()
client.loop_stop()
Betiği python edge_sim.py ile çalıştırın. Grubu mosquitto_sub -h broker.connectmq.com -p 1883 -i watcher-1234 -t "spBv1.0/demo-xxxxxx/#" -v ile izleyin; grup adını betiğin yazdırdığıyla değiştirin. Will'i iş başında görmek için Ctrl+C'ye basmak yerine süreci sonlandırın: keepalive süresi dolduktan sonra broker, node adına NDEATH yayınlar.
Herkese açık MQTT test broker'ı herkes tarafından okunabilir ve client başına saniyede 10 mesaja izin verir; bu yüzden yayın aralığını rahat tutun ve asla gerçek tesis verisi göndermeyin. Gerçek bir kurulum için TLS ile 8883 portuna geçin ve portaldan aldığınız YOUR_USERNAME, YOUR_PASSWORD ve YOUR_CLIENT_ID değerlerini kullanın.
Birth ve Death Mesajlarını Çözülmüş Olarak Görmek
Payload'lar Protobuf olduğu için mosquitto_sub çıktısı kısmen binary görünecektir. ConnectMQ'da topic gezgini Sparkplug B'yi çözer; böylece NBIRTH'ü açıp bdSeq, Node Control/Rebirth ve her cihaz metriğini adıyla görebilirsiniz. Bu, NDEATH'teki bdSeq'in NBIRTH ile eşleştiğini ve seq'in boşluksuz arttığını doğrulamanın en hızlı yoludur. Kendi decoder'ınızı yazmak istiyorsanız Python ile Sparkplug B çözme yazısını izleyin.
Yaygın Hatalar
| Hata | Etkisi | Çözüm |
|---|---|---|
| Will, bağlandıktan sonra ayarlanmış | Çökmede NDEATH yok | will_set çağrısını connect öncesinde yapın |
| NBIRTH ile NDEATH arasında bdSeq farklı | Host death mesajlarını yok sayar veya yanlış uygular | Bir oturum için aynı değeri kullanın |
| DBIRTH'ten önce DDATA | Host'ta metrik tanımı yok | Her zaman önce birth mesajlarını yayınlayın |
| Rebirth'te seq sıfırlanmamış | Host sahte boşluklar algılar | NBIRTH her zaman seq 0 kullanır |
| Retained birth mesajları | Bayat birth'ler yeni host'lara yeniden oynatılır | Birth ve death mesajları asla retained olmaz |
| Kalıcı oturum | Eski abonelikler ve kuyrukta bekleyen komutlar | Clean session kullanın |
Birth ve Death Mimarinize Nasıl Oturur?
Birth ve death sertifikaları, bir yığın MQTT topic'ini güvenilir ve durumdan haberdar bir veri katmanına dönüştüren şeydir; Sparkplug'ın Unified Namespace tasarımlarında ve SCADA'da yaygın olmasının nedeni de budur. Daha geniş bir resim için MQTT ile Endüstriyel IoT rehberine göz atın. Üretimde will mekanizmasının güvenilirliği broker'a da bağlıdır; bu nedenle çoğu ekip Sparkplug'ı masanın altındaki bir kutu yerine yönetilen bir MQTT broker üzerinde çalıştırır.
ConnectMQ ile Başlayın
app.connectmq.com adresinde kredi kartı gerekmeden ücretsiz bir Serverless broker oluşturun. Simülatörü oluşturulan kimlik bilgileriyle kendi broker'ınıza yönlendirin; ardından NBIRTH, DBIRTH, DDATA ve NDEATH mesajlarını ConnectMQ portalında canlı ve çözülmüş olarak izleyin.
Sık Sorulan Sorular
Sparkplug birth sertifikaları retained mıdır?
Hayır. Birth ve death mesajları retain bayrağı olmadan yayınlanır. Daha sonra başlayan bir host, retained mesajlara güvenmek yerine güncel birth mesajlarını almak için bir rebirth komutu gönderir.
NDEATH mesajını kim yayınlar?
Genellikle broker, çünkü NDEATH edge node'un MQTT will'i olarak kaydedilir. Düzgün şekilde kapanan bir node, bağlantıyı kesmeden önce bunu kendisi yayınlayabilir.
Node öldüğünde her cihaz için DDEATH gerekir mi?
Hayır. NDEATH geldiğinde host, o node'un altındaki tüm cihazları çevrimdışı kabul eder. DDEATH yalnızca node bağlı kalırken tek bir cihaz kaybedildiğinde gerekir.
seq 255'e ulaştığında ne olur?
0'a döner ve devam eder. Onu yalnızca NBIRTH kasıtlı olarak sıfırlar; bunun dışındaki her beklenmedik atlama, kaçırılmış bir mesaja işaret eder.



