Eclipse Tahu, Sparkplug spesifikasyonunun Java, Python ve C dillerinde kütüphaneler ve örnekler içeren açık kaynaklı referans implementasyonudur. Bu rehberde Tahu deposunun her bölümünün ne işe yaradığını, nasıl derleneceğini, ilk kullanımda insanları zorlayan tuzakları ve Tahu tabanlı bir edge node'u gerçek bir MQTT broker'a bağlayıp birth ve veri mesajlarının gelişini nasıl izleyeceğinizi öğreneceksiniz.
Eclipse Tahu Nedir, Ne Değildir?
Sparkplug, Eclipse Foundation bünyesinde yönetilir ve Tahu, spesifikasyonu çalışan koda dönüştüren projedir. Üç şey sunar:
- Sparkplug B payload'ları için Protobuf tanımı olan
sparkplug_b.protove her dil için bundan üretilmiş kod. - Payload oluşturan ve parse eden yardımcı kütüphaneler: BIRTH ve DEATH payload'ları oluşturma, metrikleri doğru veri tipleriyle ekleme, sıra numaralarını yönetme.
- Minimal bir edge node ile host uygulamasını gösteren ve üreticilerin implementasyonlarını spesifikasyona karşı kontrol etmelerine yardımcı olan örnekler ve uyumluluk araçları.
Eclipse Tahu'nun ne olmadığına gelince: bir MQTT broker değildir, bir SCADA sistemi değildir ve bir gateway ürünü değildir. Her Tahu örneği, sizin sağladığınız bir broker'a sıradan bir MQTT client olarak bağlanır. Sparkplug'ın tüm amacı bu ayrımdır. Edge node ve host Sparkplug konuşur; ortadaki MQTT broker ise yalnızca standartlara uygun bir MQTT sunucusu olmak zorundadır.
Tahu aynı zamanda bir referans kodudur. Bir üretim gateway'ine olduğu gibi yerleştirilmek için değil, açık ve doğru olması için yazılmıştır. Birçok ekip Protobuf tanımlarını ve payload yardımcılarını doğrudan kullanır ve bunların etrafına kendi oturum yönetimini yazar; aşağıda biz de tam olarak bunu yapacağız.
Depoda Bir Tur
Kaynak kod GitHub'daki Eclipse Tahu deposunda bulunur. Keşfetmek için klonlayın:
git clone https://github.com/eclipse-tahu/tahu.git
cd tahu
ls
Düzen dillere göre organize edilmiştir. Klasör adları sürümler arasında değişti; bu yüzden bu tabloyu kesin bir liste yerine bir harita olarak görün ve klonladığınız branch'in README dosyasını kontrol edin.
| Alan | Ne bulursunuz | Tipik kullanım |
|---|---|---|
sparkplug_b (proto) |
Sparkplug B payload'ları için .proto tanımı |
Herhangi bir dil için binding üretmek |
java |
Core kütüphane, payload oluşturucular ve decoder'lar, edge ve host örnekleri, uyumluluk testleri | JVM gateway'leri ve host uygulamaları |
python |
sparkplug_b.py yardımcıları ve üretilmiş sparkplug_b_pb2.py içeren core, artı örnekler |
Betikler, simülatörler, test araçları |
c |
nanopb üzerine kurulu core payload kodlaması, artı bir örnek client | Gömülü gateway'ler ve kısıtlı cihazlar |
javascript |
Node.js için payload kodlama yardımcıları | Node tabanlı araçlar ve Node-RED tarzı akışlar |
Java
Java implementasyonu en eksiksiz olanıdır. Payload'lar ve metrikler için model sınıfları, encoder ve decoder'lar ve daha üst seviye edge node ile host örnekleri içerir. Maven ile derlenir:
cd java
mvn clean install -DskipTests
Ortaya çıkan artifact'lar kendi Maven veya Gradle projenizden kullanılabilir. Bir host uygulaması yazıyorsanız veya JVM tabanlı bir SCADA ya da MES ile entegrasyon yapıyorsanız Java doğal seçimdir.
Python
Python klasörü, sürekli kullanacağınız iki dosya içerir. sparkplug_b_pb2.py üretilmiş Protobuf modülüdür; sparkplug_b.py ise getNodeBirthPayload, getDeviceBirthPayload, getDdataPayload, getNodeDeathPayload ve addMetric gibi yardımcılar ile bir MetricDataType enumerasyonu ekler. Örnekler klasörü, birth yayınlayan, veri gönderen ve komutlara yanıt veren basit bir edge node gösterir.
C
C implementasyonu, mikrodenetleyiciler için tasarlanmış küçük bir Protobuf çalışma zamanı olan nanopb'yi kullanarak Sparkplug payload'larını kodlar ve çözer. Gömülü bir Linux gateway'inde veya belleği kısıtlı bir firmware'de Sparkplug'a ihtiyacınız varsa başlangıç noktası budur. Örnek client, encoder'ı bir MQTT kütüphanesiyle eşleştirir; o kütüphanenin geliştirme başlık dosyalarını kurduktan sonra sağlanan Makefile ile derlersiniz.
Yaygın Eclipse Tahu Tuzakları
Tahu ile ilk gün yaşanan sorunların çoğu Sparkplug sorunu değil, ortam sorunudur.
- paho-mqtt 2.x eski Python örneklerini bozar. Tahu Python örnekleri paho-mqtt 1.x'e göre yazılmıştır. paho-mqtt 2.x ile
mqtt.Client()ilk argüman olarak bir callback API sürümü gerektirir. Örnekler için yapip install "paho-mqtt<2"ile sürümü sabitleyin ya da eski callback imzalarını korumak için client'ımqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id=...)olarak oluşturun. - Protobuf çalışma zamanı uyumsuzluğu. Eski bir
protocile üretilmişsparkplug_b_pb2.py, yeni birprotobufpaketiyle "Descriptors cannot be created directly" hatası verebilir. Güncel bir derleyiciyleprotoc --python_out=. sparkplug_b.protokullanarak yeniden üretin. - İçe aktarma yolları. Örnekler core yardımcılarını göreli bir yol ekleyerek içe aktarır. Bir örneği başka bir yere kopyalarsanız,
sparkplug_b.pyvesparkplug_b_pb2.pydosyalarını da yanına kopyalayın. - Sabit kodlanmış bağlantı ayarları. Örnekler varsayılan olarak
localhostadresini gösterir. Dosyanın başındaki broker host'unu, portu, grup ID'sini, edge node ID'sini ve kimlik bilgilerini düzenleyin. - Herkese açık broker'larda paylaşılan grup ID'leri. Sparkplug topic'leri her zaman
spBv1.0ile başlar; bu yüzden herkese açık bir broker'da başkalarının testleriyle çakışmamak için rastgele bir grup ID'si kullanın.
Bir Tahu Edge Node'unu MQTT Broker'a Bağlamak
Aşağıdaki betik, Tahu'nun Python yardımcılarını paho-mqtt 2.x ile kullanır. Tahu'nun Python core klasöründen sparkplug_b.py ve sparkplug_b_pb2.py dosyalarını boş bir dizine kopyalayın, bu dosyayı yanlarına ekleyin ve bağımlılıkları pip install "paho-mqtt>=2.0" protobuf ile kurun.
import random
import time
import paho.mqtt.client as mqtt
from sparkplug_b import (
MetricDataType,
addMetric,
getDdataPayload,
getDeviceBirthPayload,
getNodeBirthPayload,
getNodeDeathPayload,
)
BROKER = "broker.connectmq.com"
PORT = 1883
GROUP = "tahu-demo-5mz8" # herkese açık broker için rastgele grup ID'si
NODE = "tahu-edge-01"
DEVICE = "pump-01"
CLIENT_ID = f"tahu-edge-{random.randint(1000, 9999)}"
def t(msg_type, device=None):
base = f"spBv1.0/{GROUP}/{msg_type}/{NODE}"
return f"{base}/{device}" if device else base
def publish_births(client):
nbirth = getNodeBirthPayload()
addMetric(nbirth, "Node Control/Rebirth", None, MetricDataType.Boolean, False)
client.publish(t("NBIRTH"), bytearray(nbirth.SerializeToString()), 0, False)
dbirth = getDeviceBirthPayload()
addMetric(dbirth, "Flow", None, MetricDataType.Float, 12.5)
addMetric(dbirth, "Pressure", None, MetricDataType.Float, 3.1)
addMetric(dbirth, "Running", None, MetricDataType.Boolean, True)
client.publish(t("DBIRTH", DEVICE), bytearray(dbirth.SerializeToString()), 0, False)
print("NBIRTH and DBIRTH published")
def on_connect(client, userdata, flags, reason_code, properties):
print("connected:", reason_code)
client.subscribe(t("NCMD"))
publish_births(client)
def on_message(client, userdata, msg):
print("command received on", msg.topic)
publish_births(client) # bu demoda her NCMD'yi rebirth isteği olarak ele al
# Death payload'ı birth'ten önce oluşturulmalı ki ikisi de aynı bdSeq'i taşısın
death = getNodeDeathPayload()
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.on_connect = on_connect
client.on_message = on_message
client.will_set(t("NDEATH"), bytearray(death.SerializeToString()), 1, False)
client.connect(BROKER, PORT, 60)
client.loop_start()
try:
while True:
time.sleep(3)
ddata = getDdataPayload()
addMetric(ddata, "Flow", None, MetricDataType.Float, round(random.uniform(11, 14), 2))
addMetric(ddata, "Pressure", None, MetricDataType.Float, round(random.uniform(2.8, 3.4), 2))
client.publish(t("DDATA", DEVICE), bytearray(ddata.SerializeToString()), 0, False)
print("DDATA published")
except KeyboardInterrupt:
client.loop_stop()
client.disconnect()
getNodeDeathPayload() ve getNodeBirthPayload() çağrılarının sırası önemlidir, çünkü Tahu'nun yardımcıları bdSeq sayacını dahili olarak yönetir ve will olarak kaydedilen NDEATH, ardından gelen NBIRTH ile aynı değeri taşımalıdır. Elinizdeki yardımcıların kopyası farklı davranıyorsa, her iki payload'daki bdSeq metriğini inceleyin ve buna göre ayarlayın.
Betiği çalıştırın ve başka bir terminalde gruba abone olun:
mosquitto_sub -h broker.connectmq.com -p 1883 -i tahu-watch-5mz8 -t "spBv1.0/tahu-demo-5mz8/#" -v
Topic'lerin binary payload'larla geldiğini göreceksiniz. Metrikleri okumak için trafiği bir ConnectMQ portalında açın: canlı topic gezgini, Protobuf veya JSON fark etmeksizin Sparkplug B payload'larını veri tipleri ve değerleriyle adlandırılmış metriklere çözer. Bu, bir SCADA host'u devreye girmeden önce Tahu'nun beklediğiniz çıktıyı ürettiğini hızlıca doğrulamanızı sağlar. Az önce kullandığınız broker ücretsiz herkese açık MQTT broker'dır; herkes tarafından okunabilir, bu yüzden gerçek tag adlarını ve değerlerini oradan uzak tutun.
Referans Koddan Gerçek Bir Edge Node'a
Örnek çalıştıktan sonra, bir üretim edge node'u Tahu'nun hazır olarak sunduğundan fazlasına ihtiyaç duyar:
- Kalıcı bdSeq. Sayacın süreç yeniden başlatmaları arasında artması için onu diskte saklayın.
- Report by exception. Gürültülü analog sinyaller için ölü bantlarla (deadband) yalnızca değişen değerleri yayınlayın.
- Store and forward. Broker kesintileri sırasında veriyi tamponlayın ve historical bayraklarıyla yeniden oynatın.
- Alias'lar. Kısıtlı bağlantılarda Sparkplug metrik alias'larını etkinleştirin.
- Primary host farkındalığı. Sparkplug 3.0'da edge node'lar, birth yayınlamadan önce primary host'un STATE mesajını bekleyebilir.
- TLS ve kimlik bilgileri. Client başına kimlik bilgileriyle 8883 portuna geçin.
Tahu yardımcıları olmadan tamamen kendi kendine yeten bir betik istiyorsanız, Sparkplug B edge node simülatörü yazımız payload'ları doğrudan üretilmiş Protobuf modülünden oluşturur ve sıra numaraları ile rebirth'leri açıkça yönetir. Payload'ın iç yapısı için Sparkplug B veri tipleri yazısına bakın. Spesifikasyonun kendisi Eclipse Sparkplug çalışma grubu tarafından yayınlanır.
Üretim için Tahu tabanlı node'ları özel bir broker'a bağlayın. ConnectMQ'da portalda bir broker oluşturun, oluşturulan YOUR_USERNAME, YOUR_PASSWORD ve YOUR_CLIENT_ID değerlerini kopyalayın, betikte client ID'yi ayarlayın, client.username_pw_set(...) ve client.tls_set() ekleyin ve 8883 portuna bağlanın. ConnectMQ ardından çözülmüş Sparkplug B verisini connectmq/factory1/production/line1/cnc1/telemetry gibi ISA-95 topic'lerine yeniden yayınlayabilir; Sparkplug kullanmayan tüketiciler bunları düz veri olarak okuyabilir. Daha geniş mimari endüstriyel IoT MQTT rehberimizde ele alınıyor.
Eclipse Tahu'yu ConnectMQ'ya Bağlayın
Tahu size doğru payload'lar sunar; yine de edge ile host arasında güvenilir bir broker'a ihtiyacınız vardır. ConnectMQ; MQTT 3.1.1 ve 5.0, 8883'te TLS, Sparkplug B çözme ve ISA-95 yeniden yayınlama sunan barındırılan bir MQTT broker'dır. app.connectmq.com adresinde kredi kartı gerekmeden ücretsiz Serverless planında bir broker oluşturun ve Tahu edge node'unuzu birkaç dakika içinde ona yönlendirin.
Sık Sorulan Sorular
Eclipse Tahu bir broker mı?
Hayır. Eclipse Tahu, Sparkplug kütüphaneleri ve örnekleri sunar. Onunla oluşturulan edge node'lar ve host'lar, standartlara uygun herhangi bir MQTT broker'a MQTT client olarak bağlanır.
Hangi Tahu dilini kullanmalıyım?
Host uygulamaları ve JVM gateway'leri için Java'yı, betikler, simülatörler ve testler için Python'u, bellek bütçesi kısıtlı gömülü gateway'ler için ise C'yi kullanın.
Tahu Python örnekleri paho-mqtt 2.x ile neden başarısız oluyor?
paho-mqtt 2.x, client oluşturulurken bir callback API sürümü gerektirir. Örnekler için paho-mqtt'yi 2.0'ın altına sabitleyin veya callback imzalarını korumak için mqtt.CallbackAPIVersion.VERSION1 geçirin.
Tahu üretime hazır mı?
Doğruluğa odaklanmış bir referans kodudur. Birçok ekip Protobuf tanımlarını ve payload yardımcılarını üretimde kullanırken kendi oturum yönetimini, tamponlamasını ve güvenliğini ekler.



