İyi bir UNS topic yapısı, bir unified namespace'i gezilebilir kılan şeydir: tesisi tanıyan herkes, belgelere bakmadan bir değerin nerede durduğunu tahmin edebilir. Bu rehber size kesikli ve proses üretimi için hazır topic ağaçları, bunları temiz tutan adlandırma ve payload kuralları ve hatalı topic'leri broker'a ulaşmadan durdurmak için CI'da veya gateway'de çalıştırabileceğiniz küçük bir doğrulayıcı sunuyor.
Bir UNS Topic Yapısının Arkasındaki İlkeler
Bu yazıdaki her örnek aynı beş ilkeyi izler. Ağaçları uyarlarsanız ilkeleri koruyun.
- Teknolojiyi değil, tesisi modelleyin. Topic'ler bir şeyin nerede olduğunu ve ne olduğunu anlatır; onu hangi protokolün veya hangi PLC markasının ürettiğini değil.
opcua/ves7/yolda yer almamalıdır. - Önce hiyerarşi, omurga olarak ISA-95. Kuruluş, saha, alan, hat veya hücre ve ekipman, operasyon ekibinin zaten anladığı bir yapı sunar. ISA-95 ekipman hiyerarşisi rehberi her seviyeyi açıklıyor.
- Mümkün olduğunda sabit derinlik. Her makine aynı seviyede durduğunda
+/+/+/+/telemetrygibi joker karakterli abonelikler tüm kuruluş genelinde çalışır. - Az sayıda yaprak türü. Her ekipman dalını
telemetry,state,alarms,eventsvecmdgibi öngörülebilir bir ad alanı kümesiyle bitirin. - Kalıcı tanımlayıcılar. Yeniden yapılanmalardan etkilenmeyen kısa, küçük harfli, tireli adlar kullanın. Varlık numaraları çoğu zaman değişen açıklayıcı adlardan daha iyidir.
Örnek 1: Kesikli Üretim
Montaj hatları, talaşlı imalat hücreleri ve ortak yardımcı tesisleri olan kesikli bir tesis:
acme/ enterprise
dallas/ site
machining/ area
cell-03/ work cell
cnc-01/ equipment
telemetry {"spindle_rpm":..., "load_pct":..., "ts":...}
state "running" | "idle" | "down" (retained)
alarms active alarm list (retained)
events/cycle-complete one message per finished part
cmd/ commands, request/response
robot-01/
telemetry
state
assembly/
line-02/ production line
station-10/
telemetry
events/part-scanned
station-20/
telemetry
line-02/kpi/oee line-level calculated values
utilities/
compressors/
comp-01/telemetry
Hat seviyesindeki kpi dalına dikkat edin. OEE veya verim gibi hesaplanmış değerler, onları hesaplayan uygulama tarafından, tanımladıkları seviyede yayınlanmalıdır. Bu, ham makine verisi ile türetilmiş veriyi aynı ağaçta tutarken birbirinden net biçimde ayırır.
Örnek 2: Proses Üretimi
Proses tesisleri hatlar ve istasyonlar yerine proses hücreleri ve üniteler üzerinden düşünür. ISA-95 her ikisini de kapsar; bu yüzden ağacın kelime dağarcığı değişir ama biçimi değişmez:
acme/
izmir/ site
brewing/ area
brewhouse-1/ process cell
mash-tun/ unit
telemetry {"temp_c":..., "level_pct":..., "ts":...}
state "heating" | "resting" | "transferring"
batch current batch id and recipe (retained)
lauter-tun/
telemetry
fermentation/
fv-07/
telemetry
batch
utilities/
boiler-1/telemetry
water-treatment/ro-1/telemetry
batch yaprağı, proses tesislerinde iş emrinin karşılığıdır: retained, küçük ve parti değiştiğinde güncellenir. Tüketiciler parti bağlamını telemetriyle ayrı bir veritabanı sorgusu yapmadan, topic yolu üzerinden birleştirir.
Örnek 3: Ortak Hizmetlere Sahip Çok Sahalı Kuruluş
Birden fazla saha bir broker'ı veya köprülenmiş bir namespace'i paylaştığında, kuruluş sistemleri için üst seviyede bir dal ekleyin; böylece MES, ERP ve kalite verisi ekipmanmış gibi davranmayan bir yuvaya kavuşur:
acme/dallas/... site trees as above
acme/izmir/...
acme/_enterprise/erp/work-orders/dallas work orders per site (retained)
acme/_enterprise/quality/spc/dallas/line-02
acme/_enterprise/mes/schedule/izmir
Baştaki alt çizgi, dalı saha adlarından ayrı sıralar ve bunun fiziksel bir konum olmadığını açıkça gösterir.
Sparkplug B, UNS Topic Yapısına Nasıl Uyar?
Sparkplug B kendi sabit topic formatını kullanır: spBv1.0/<group>/<message type>/<edge node>/<device>. Bu format, tesis hiyerarşisine göre gezinmek için değil, edge node'lar ile host uygulamaları arasındaki durum yönetimi için optimize edilmiştir. Sparkplug topic namespace yazımız bunu ayrıntılı olarak açıklıyor.
Seçim yapmak zorunda değilsiniz. Yaygın bir desen, edge-host trafiği için Sparkplug'ı korur ve değerleri diğer herkes için ISA-95 ağacına yeniden yayınlar. ConnectMQ bunu Sparkplug B trafiği için otomatik olarak yapar: Protobuf veya JSON payload'u çözer ve ISA-95 topic'lerine yeniden yayınlar; böylece spBv1.0/factory1/DDATA/line1/cnc1, connectmq/factory1/production/line1/cnc1/telemetry olur. Panolar ve historian'lar ISA-95 ağacındaki okunabilir JSON'a abone olurken SCADA host'ları yerel Sparkplug kullanmaya devam eder.
Adlandırma ve Payload Kuralları
| Kural | İyi | Kaçının |
|---|---|---|
| Yalnızca küçük harf | line-02 |
Line_02, LINE02 |
| Tire kullanın, boşluk yok | mash-tun |
mash tun, mash%20tun |
| Başta veya sonda eğik çizgi yok | acme/dallas/... |
/acme/dallas/ |
Adlarda joker karakter veya $ yok |
cnc-01 |
cnc#1, $cnc |
| Birimler alan adlarında | temp_c, speed_bpm |
temp, speed |
| Payload'larda zaman damgası | "ts": "2026-10-16T08:00:00Z" |
Varış zamanına güvenmek |
| Güncel durumu retained yapın | state, batch, alarms |
Olay akışlarını retained yapmak |
| Payload'ları sürümleyin | "v": 2 |
Sessizce uyumluluğu bozan değişiklikler |
Baştaki eğik çizgi klasik bir hatadır: boş bir ilk seviye oluşturur, dolayısıyla /acme/# ve acme/# farklı aboneliklerdir. Karışık büyük-küçük harf de bir diğeridir: MQTT topic'leri büyük-küçük harfe duyarlıdır; Line-02 ve line-02 verinizi sessizce bölen iki farklı dal haline gelir.
Topic'leri Broker'a Ulaşmadan Doğrulayın
Aşağıdaki betik topic'leri yukarıdaki kurallara ve beş seviyeli ekipman yapısına göre kontrol eder. Bir gateway'de, etiket eşleme dosyanız üzerinde bir CI testinde veya ihlalleri raporlayan bir izleme abonesi olarak kullanın.
import re
LEVEL = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$")
LEAVES = {"telemetry", "state", "alarms", "batch", "events", "cmd", "kpi"}
def validate(topic: str, depth: int = 5) -> list[str]:
"""Sorunların listesini döndürür; boş liste topic'in geçerli olduğu anlamına gelir."""
problems = []
if topic.startswith("/") or topic.endswith("/"):
problems.append("leading or trailing slash")
levels = topic.strip("/").split("/")
if any(ch in topic for ch in "+#$"):
problems.append("wildcard or $ character in topic name")
if any(" " in level for level in levels):
problems.append("space in topic level")
if len(levels) < depth + 1:
problems.append(f"expected at least {depth + 1} levels, got {len(levels)}")
return problems
for level in levels[:depth]:
if not (LEVEL.match(level) or level.startswith("_")):
problems.append(f"level '{level}' is not lowercase-hyphenated")
if levels[depth] not in LEAVES:
problems.append(f"leaf '{levels[depth]}' not in {sorted(LEAVES)}")
return problems
if __name__ == "__main__":
tests = [
"acme/dallas/machining/cell-03/cnc-01/telemetry",
"acme/dallas/machining/cell-03/CNC_01/telemetry",
"/acme/dallas/assembly/line-02/station-10/telemetry",
"acme/dallas/assembly/line-02/station-10/temperature",
]
for t in tests:
result = validate(t)
print("OK " if not result else "FAIL", t, "" if not result else result)
Betiği python validate_topics.py ile çalıştırın ve LEAVES ile depth değerlerini kendi standardınıza göre ayarlayın.
Tüketicileri Bozmadan Yapıyı Geliştirmek
Hiçbir topic yapısı gerçek bir tesisle karşılaştıktan sonra değişmeden kalmaz. Hatlar yeniden kurulur, makineler hücreler arasında taşınır, kendi adlandırma alışkanlıkları olan yeni bir saha satın alınır. Amaç değişimden kaçınmak değil, onu güvenli hale getirmektir.
- Ekleyin, yerinde asla yeniden adlandırmayın. Bir dalın değişmesi gerektiğinde, belirli bir süre boyunca hem yeni hem eski yola paralel yayın yapın, ardından eskisini emekliye ayırın. Kullanımdan kaldırma tarihini her tüketici sahibine duyurun.
- Emekliye ayırırken retained message'ları temizleyin. Emekliye ayrılmış bir dal, yeni abonelere hâlâ retained değerler döndürür. Bunları kaldırmak için her eski durum topic'ine boş bir retained message yayınlayın.
- Bir kayıt defteri tutun. Sürüm kontrolünde her dalı, sahibini, yaprak türlerini ve payload şema sürümünü listeleyen basit bir dosya yeterlidir. Yukarıdaki doğrulayıcı kurallarını bu dosyadan okuyabilir.
- Topic'leri değil, payload'ları sürümleyin. Şema değiştiğinde payload'a bir
valanı koyun. Yolunda/v2/bulunan topic'ler çoğalma eğilimindedir ve joker karakterli abonelikleri karıştırır. - Yeni dalları gözden geçirin. Bir gateway devreye girmeden önce namespace sahibinin yapacağı kısa bir inceleme, sorunların çoğunu düzeltmesi hâlâ ucuzken yakalar.
Yapıya tüm tesisin bağımlı olduğu bir API gibi davranın; çünkü panolar, historian'lar ve MES entegrasyonları ona abone olduğunda tam olarak buna dönüşür.
Yapıyı Canlı Bir Broker'da Deneyin
Bir yapıyı yaygınlaştırmadan önce birkaç örnek mesaj yayınlayın ve bunlar arasında gezinin. broker.connectmq.com adresindeki herkese açık MQTT test broker'ında bunu hesap olmadan yapabilirsiniz; yeter ki benzersiz bir önek kullanın ve herkese açık alanın herkes tarafından okunabildiğini unutmayın. Herkese açık broker 8 topic seviyesine izin verir; bu yüzden kuruluş seviyesini çıkardığınızda connectmq/demo/<id>/ artı beş seviyeli ağaç ve bir yaprak tam olarak sığar:
mosquitto_pub -h broker.connectmq.com -p 1883 -i uns-test-pub-q7 -r \
-t "connectmq/demo/q7w2/dallas/machining/cell-03/cnc-01/state" -m "running"
mosquitto_sub -h broker.connectmq.com -p 1883 -i uns-test-sub-q7 \
-t "connectmq/demo/q7w2/dallas/+/+/+/state" -v
Özel bir ConnectMQ broker'ında demo öneki olmadan tam ağacı kullanabilirsiniz; portalın canlı topic gezgini ve ISA-95 cihazlar görünümü, cihazların doğru kuruluş, saha, alan ve hatta yer alıp almadığını bir bakışta gösterir. Adım adım kodlama kuralları için ISA-95 MQTT topic'leri yazısıyla devam edin; kurulum sürecinin tamamı için unified namespace nasıl kurulur rehberine bakın. Genel tablo endüstriyel IoT MQTT rehberimizde yer alıyor.
UNS Topic Yapınızı ConnectMQ Üzerine Taşıyın
Bir topic yapısı, onu taşıyan broker ve üzerindeki görünürlüğünüz kadar iyidir. ConnectMQ; ISA-95 ve unified namespace topic'lerini algılayan, Sparkplug B'yi çözüp ISA-95 ağacınıza yeniden yayınlayan tam yönetilen bir MQTT hizmetidir. app.connectmq.com adresinde kredi kartı gerektirmeden ücretsiz Serverless planla bir broker oluşturun ve ilk namespace dalınızı dakikalar içinde yayınlayın.
Sık Sorulan Sorular
Bir UNS topic yapısı kaç seviyeden oluşmalı?
Çoğu tesis beş veya altı seviye kullanır: kuruluş, saha, alan, hat veya hücre, ekipman ve telemetry ya da state gibi bir yaprak. Sabit derinlik, joker karakterli abonelikleri basit tutar.
Her metriğin kendi topic'i olmalı mı?
Her iki yaklaşım da işe yarar. Ekipman telemetri topic'i başına tek bir JSON nesnesi daha basit ve daha ucuzdur; metrik başına bir topic ise topic'leri doğrudan etiketlere eşleyen araçlara uygundur. Her yaprak türü için birini seçin ve tutarlı biçimde uygulayın.
Hesaplanan KPI'lar nereye ait?
Tanımladıkları seviyeye; onları hesaplayan uygulama tarafından yayınlanırlar. Örneğin hattın altındaki bir kpi/oee dalı.
Sparkplug B topic'leri bir UNS'nin parçası olabilir mi?
Evet, ancak tesis hiyerarşisine göre düzenlenmezler. Tüm tüketicilerin tek bir ağaçta gezinebilmesi için Sparkplug değerlerini ISA-95 topic'lerine yeniden yayınlayın.



