Endüstriyel IoT

MTConnect'ten MQTT'ye: CNC Makine Verisini Panolara Aktarmak

MTConnect agent'ları CNC verisini HTTP ve XML üzerinden sunar. Agent'ın sıra numaralarını izleyen, önemli veri öğelerini seçen ve makine durumunu panolar ve analitik için MQTT üzerinden yayımlayan bir köprü kurun.

XML akışı bir MTConnect'ten MQTT'ye köprü tarafından canlı pano topic'lerine dönüştürülen bir MTConnect agent'ını besleyen CNC makineleri
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

MTConnect'ten MQTT'ye köprü, bir CNC makinesinin standartlaştırılmış verisinden canlı panolara, uyarılara ve kullanım raporlarına giden en kısa yoldur. Bu eğitimde bir MTConnect agent'ının veriyi nasıl sunduğunu öğrenecek, ardından agent'ın sıra numaralarını hiçbir gözlemi kaçırmadan izleyen, çalışma durumu, iş mili devri ve parça sayısı gibi veri öğelerini okunabilir topic'lere eşleyen ve bunları MQTT üzerinden yayımlayan bir Python köprüsü kuracaksınız. Aynı köprü tek bir makine için de bütün bir hücre için de çalışır.

MTConnect Makine Verisini Nasıl Sunar?

MTConnect, üretim ekipmanları, özellikle takım tezgâhları için açık bir standarttır. Bir sözlük ("Execution", "SpindleSpeed" veya "PartCount"un ne anlama geldiği) ve bir agent tarafından sunulan salt okunur bir HTTP arayüzü tanımlar. Makineler agent ile, çoğu zaman kontrol üreticisi tarafından sağlanan veya kontrol ünitesine yerleşik olan bir adapter aracılığıyla konuşur; client'lar ise agent'tan okur.

Agent üç ana istek sunar:

İstek Döndürdüğü Ne için kullanılır
/probe Cihaz modeli: ID'leri, tipleri ve birimleriyle bileşenler ve veri öğeleri Başlangıçta bir kez veri öğesi kataloğu oluşturmak
/current Her veri öğesinin son değeri ve başlıktaki sıra bilgisi Başlangıç durumu ve hatalardan sonra yeniden senkronizasyon
/sample?from=N&count=M N sırasından itibaren en fazla M öğeye kadar her gözlem Hiçbirini kaçırmadan değişiklikleri izlemek

Her gözlem, agent tarafından atanan bir sequence numarası, bir timestamp ve bir dataItemId taşır. Yanıt başlığı firstSequence, lastSequence, nextSequence ve bir instanceId içerir. Bu dört değer güvenilir bir köprünün anahtarıdır: /current ile başlarsınız, nextSequence değerini hatırlarsınız ve oradan itibaren örnek istersiniz.

MTConnect gözlemleri, MQTT'de onlara nasıl davranmanız gerektiğiyle düzgün şekilde örtüşen üç kategoriye ayrılır:

  • Sample'lar, iş mili devri, yük veya konum gibi sayısal ölçümlerdir.
  • Event'ler, çalışma durumu, kontrol modu, program adı veya parça sayısı gibi ayrık durumlar ya da değerlerdir.
  • Condition'lar sağlığı tanımlar: Normal, Warning, Fault veya Unavailable; çoğu zaman yerel bir alarm koduyla birlikte.

Değeri bilinmeyen bir veri öğesi UNAVAILABLE raporlar. Köprünüz bunu gizlememeli, olduğu gibi iletmelidir; çünkü "makine kapalı veya bağlantısı kopuk" önemli bir bilgidir.

MTConnect'i MQTT'ye Neden Köprülemeli?

MTConnect çekme (pull) tabanlıdır ve XML ağırlıklıdır. Tek bir pano için bu sorun değildir, ama her yeni tüketici agent'ı ayrı ayrı sorgular ve XML ayrıştırmak zorunda kalır. MQTT'ye köprülemek size itme (push) tabanlı iletim, tüketici dostu tek bir JSON biçimi, sonradan katılanlar için retained güncel durum ve makine verisini PLC, enerji ve kalite verisiyle tek bir topic hiyerarşisinde birleştirme imkânı verir. Bir Unified Namespace kuruyorsanız MTConnect makineleri onu besleyen kaynaklardan biri olur; ISA-95 MQTT topic'leri rehberimiz onları nereye yerleştireceğinizi gösteriyor.

MTConnect referans agent'ının yeni sürümleri, yerleşik bir MQTT sink aracılığıyla doğrudan bir MQTT broker'a da yayın yapabilir. Agent sürümünüz bunu destekliyorsa değerlendirmeye değer; yapılandırma anahtarları sürümler arasında farklılık gösterdiğinden agent'ın kendi dokümantasyonunu izleyin. Bu eğitimdeki köprü her agent sürümüyle çalışır ve topic adları ile payload biçimi üzerinde size tam kontrol sağlar.

Ön Koşullar

  • requests ve paho-mqtt 2.x yüklü Python 3.10 veya daha yenisi.
  • http://192.168.10.50:5000 gibi bir MTConnect agent URL'si. Bağlı bir makineniz yoksa referans agent projesi, yerel olarak çalıştırabileceğiniz örnek yapılandırmalar ve bir simülatör içerir.
  • Bir broker. Test için benzersiz bir topic önekiyle ücretsiz public MQTT broker'ı kullanın.
pip install requests "paho-mqtt>=2.0"
curl -s http://localhost:5000/probe | head -40     # agent'ın yanıt verdiğini kontrol edin ve veri öğelerini listeleyin

1. Adım: Veri Öğelerini Seçin

Modern bir CNC yüzlerce veri öğesi sunabilir. Her şeyi değil, tüketicilerin ihtiyaç duyduğunu yayımlayın. Kullanım ve durum panoları için pratik bir başlangıç seti:

MTConnect tipi Kategori Örnek değerler Neden önemli
AVAILABILITY Event AVAILABLE, UNAVAILABLE Makine hiç bağlı mı
EXECUTION Event ACTIVE, READY, INTERRUPTED, FEED_HOLD, STOPPED Kullanım takibinin özü
CONTROLLER_MODE Event AUTOMATIC, MANUAL, MANUAL_DATA_INPUT Üretimi ayardan ayırır
PROGRAM Event O1234 Hangi iş çalışıyor
PART_COUNT Event 1843 Çıktı
ROTARY_VELOCITY (iş mili) Sample 12000 Kesme faaliyeti
PATH_FEEDRATE_OVERRIDE Event veya Sample 100 Operatör müdahalesi
Sistem ve mantık condition'ları Condition Normal, Warning, Fault Alarmlar

Agent'ınıza karşı /probe çalıştırın ve istediğiniz her veri öğesinin id değerini not edin. ID'ler agent'ı yapılandıran kişi tarafından seçilir; bu yüzden kurulumlar arasında farklılık gösterir.

2. Adım: MTConnect'ten MQTT'ye Köprü

Köprü veri öğesi ID'lerini topic adlarına çözümler, başlangıç durumu için /current okur, ardından /sample üzerinde döngüye girer. Agent yeniden başlatmalarını (yeni bir instanceId) ve tampon taşmalarını (firstSequence değerinden eski bir from) algılar ve iki durumda da yeniden senkronize olur.

# mtconnect_mqtt_bridge.py - bir MTConnect agent'ını izle ve gözlemleri MQTT'ye yayımla
import json, logging, time, uuid
import xml.etree.ElementTree as ET
import paho.mqtt.client as mqtt
import requests

logging.basicConfig(level=logging.INFO)
log = logging.getLogger("mtc")

AGENT = "http://localhost:5000"
TOPIC_ROOT = "connectmq/demo/f40b/shop1/cnc"        # kendi rastgele id'niz
INTERVAL = 1.0                                       # /sample istekleri arasındaki saniye
MQTT_HOST, MQTT_PORT = "broker.connectmq.com", 1883  # üretim: TLS ile 8883
MQTT_USER, MQTT_PASS = None, None                    # üretim: "YOUR_USERNAME", "YOUR_PASSWORD"
CLIENT_ID = f"mtc-bridge-{uuid.uuid4().hex[:8]}"     # üretim: "YOUR_CLIENT_ID"

# dataItemId -> topic yaprağı. ID'leri agent'ınızın /probe çıktısından alın.
WATCH = {
    "avail": "availability",
    "exec": "execution",
    "mode": "controller_mode",
    "program": "program",
    "pc": "part_count",
    "Sspeed": "spindle_speed",
    "logic_cond": "logic_condition",
}

CONDITION_TAGS = {"Normal", "Warning", "Fault", "Unavailable"}


def local(tag):
    """Sürümlü MTConnect XML namespace'ini etiket adından ayıkla."""
    return tag.rsplit("}", 1)[-1]


def fetch(path):
    r = requests.get(f"{AGENT}{path}", timeout=10)
    r.raise_for_status()
    return ET.fromstring(r.content)


def parse(root):
    header = next(e for e in root.iter() if local(e.tag) == "Header")
    observations = []
    for stream in root.iter():
        if local(stream.tag) != "DeviceStream":
            continue
        device = stream.get("name")
        for el in stream.iter():
            item_id = el.get("dataItemId")
            if item_id is None:
                continue
            tag = local(el.tag)
            if tag in CONDITION_TAGS:
                value = {"level": tag, "native_code": el.get("nativeCode"), "text": (el.text or "").strip()}
            else:
                value = (el.text or "").strip()
            observations.append({
                "device": device, "id": item_id, "value": value,
                "ts": el.get("timestamp"), "seq": int(el.get("sequence", 0)),
            })
    observations.sort(key=lambda o: o["seq"])
    return header, observations


def coerce(value):
    if isinstance(value, dict) or value == "UNAVAILABLE":
        return value
    try:
        return float(value) if "." in value else int(value)
    except ValueError:
        return value


def publish(mq, obs):
    leaf = WATCH.get(obs["id"])
    if not leaf:
        return
    topic = f"{TOPIC_ROOT}/{obs['device']}/{leaf}"
    payload = {"value": coerce(obs["value"]), "ts": obs["ts"], "seq": obs["seq"]}
    mq.publish(topic, json.dumps(payload), qos=1, retain=True)
    log.info("%s = %s", topic, payload["value"])


def main():
    mq = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
    if MQTT_USER:
        mq.username_pw_set(MQTT_USER, MQTT_PASS)
        mq.tls_set()
    mq.will_set(f"{TOPIC_ROOT}/bridge", "offline", qos=1, retain=True)
    mq.on_connect = lambda c, u, f, rc, p: c.publish(f"{TOPIC_ROOT}/bridge", "online", qos=1, retain=True)
    mq.connect(MQTT_HOST, MQTT_PORT, keepalive=30)
    mq.loop_start()

    instance, next_seq = None, None
    while True:
        try:
            if next_seq is None:                       # /current'tan (yeniden) senkronize ol
                header, obs = parse(fetch("/current"))
                instance, next_seq = header.get("instanceId"), int(header.get("nextSequence"))
                for o in obs:
                    publish(mq, o)
                log.info("synchronised: instance %s, next %s", instance, next_seq)
            else:
                header, obs = parse(fetch(f"/sample?from={next_seq}&count=1000"))
                if header.get("instanceId") != instance:
                    log.warning("agent restarted, resynchronising")
                    next_seq = None
                    continue
                for o in obs:
                    publish(mq, o)
                next_seq = int(header.get("nextSequence"))
        except (ET.ParseError, StopIteration, TypeError) as exc:
            # Hatalı XML veya normal Header içermeyen bir MTConnectError belgesi.
            log.error("unexpected agent response: %s", exc)
            next_seq = None
        except requests.RequestException as exc:
            # Ağ hataları veya aralık dışı bir "from" gibi bir hata durumu.
            log.error("agent request failed: %s", exc)
            next_seq = None
            time.sleep(5)
        time.sleep(INTERVAL)


if __name__ == "__main__":
    main()

Tasarımla ilgili birkaç nokta:

  • Sıra numarasına göre sıralama, XML gözlemleri bileşene göre gruplasa bile gözlemlerin agent'ın kaydettiği sırada yayımlanmasını garanti eder.
  • Retained message'lar, vardiya ortasında açılan bir panonun güncel çalışma durumunu, programı ve parça sayısını anında göstermesi anlamına gelir.
  • Condition'lar, seviye ve yerel alarm kodu içeren nesnelere dönüşür; böylece tüketiciler bir uyarıyı bir arızadan ayırt edebilir.
  • Hatada yeniden senkronizasyon güvenlidir: /current en son durumu yeniden yayımlar, dolayısıyla birkaç ara örnek kaybolsa bile tüketiciler sonunda doğru duruma ulaşır.

3. Adım: Çalıştırın ve İzleyin

python mtconnect_mqtt_bridge.py
mosquitto_sub -h broker.connectmq.com -p 1883 -i mtc-viewer-f40b -t "connectmq/demo/f40b/#" -v
connectmq/demo/f40b/shop1/cnc/VMC-3Axis/execution {"value": "ACTIVE", "ts": "2026-10-16T11:02:44.501Z", "seq": 90213}
connectmq/demo/f40b/shop1/cnc/VMC-3Axis/spindle_speed {"value": 11980.0, "ts": "2026-10-16T11:02:44.612Z", "seq": 90215}

Public broker client başına saniyede on mesaja izin verir; bu, durum olayları için fazlasıyla yeterlidir ama eksen konumları gibi hızlı değişen örneklerle aşılabilir. WATCH listesini odaklı tutun veya report by exception yazımızda açıklandığı gibi örnekler için bir deadband ekleyin.

Bir Makine Durum Panosu Oluşturmak

Çalışma durumu, mod ve erişilebilirlik MQTT'de olduğunda temel bir kullanım görünümü, abone olup durum değişikliklerinin süresini ölçmekten ibarettir. Yaygın, sadeleştirilmiş bir eşleme:

  1. Çalışıyor: availability AVAILABLE, mode AUTOMATIC, execution ACTIVE.
  2. Boşta: erişilebilir, execution READY veya STOPPED.
  3. Kesintiye uğramış: execution INTERRUPTED, FEED_HOLD veya OPTIONAL_STOP; çoğu zaman operatör beklemesi.
  4. Alarm: Fault seviyesindeki herhangi bir condition.
  5. Çevrim dışı: availability UNAVAILABLE veya köprü durum topic'i offline gösteriyor.

MQTT destekli herhangi bir pano aracı bu durumları hesaplayabilir; aynı topic'lere abone olan bir historian da size vardiya ve iş raporları sağlar. MQTT historian rehberimiz akışın saklanmasını ele alıyor.

Üretim Notları

  • Ağ konumlandırması. Köprüyü atölye ağında agent'ın yanında çalıştırın ve broker'a 8883 portu üzerinden dışa doğru bağlanmasına izin verin. Agent'ın HTTP portunu internete açmayın.
  • Birden fazla makine. Tek bir agent çoğu zaman birkaç cihaza hizmet verir; köprü birden fazla DeviceStream öğesini zaten işler ve her cihazı kendi dalına koyar.
  • Saat kalitesi. MTConnect zaman damgaları agent'tan veya adapter'dan gelir. Bu sunucuların NTP kullandığından emin olun, aksi hâlde süre hesaplamaları kayar.
  • Özel broker. Public broker herkese açıktır; bu yüzden gerçek makine verisi özel bir yönetilen MQTT broker'a aittir. ConnectMQ üzerinde cihaz görünümü makinelerinizi ISA-95 seviyesine göre gruplar; 3B dijital ikiz demosu da güvenli WebSocket üzerinde kurabileceğiniz türden canlı CNC görselleştirmesini gösterir.

Makine verisinin, PLC'lerin ve gateway'lerin nasıl bir araya geldiğinin tam resmi için endüstriyel IoT MQTT rehberini okuyun.

ConnectMQ ile Başlayın

CNC verinizi dakikalar içinde özel bir broker'a taşıyın. app.connectmq.com adresinde kaydolun, ücretsiz Serverless planı seçin (kredi kartı gerekmez), bir broker oluşturun ve oluşturulan kullanıcı adını, şifreyi ve client ID'yi köprüye yapıştırın. Ardından ConnectMQ portalında, örneğin iş mili devri için bir eşik uyarı kuralı tanımlayın ve makine çalışırken uyarı günlüğünü izleyin.

Sık Sorulan Sorular

MTConnect MQTT'yi yerel olarak destekliyor mu?

MTConnect standardı bir HTTP arayüzü etrafında kurulmuştur, ancak referans agent'ın yeni sürümleri gözlemleri bir broker'a yayımlayan bir MQTT sink içerir. Yukarıdaki gibi küçük bir köprü her agent sürümüyle çalışır.

Neden /current'ı sorgulamak yerine /sample kullanmalı?

/current'ı sorgulamak yalnızca son değeri gösterir ve sorgulamalar arasındaki kısa durumları kaçırabilir. nextSequence'tan itibaren /sample'ı izlemek her gözlemi sırasıyla döndürür; böylece kısa alarmlar veya duruşlar kaybolmaz.

MTConnect'te UNAVAILABLE ne anlama gelir?

Agent'ın değeri şu anda bilmediği anlamına gelir; genellikle makine veya adapter bağlı olmadığı için. Panoların makineyi çevrim dışı gösterebilmesi için onu olduğu gibi yayımlayın.

MTConnect üzerinden bir CNC'ye yazabilir miyim?

Hayır. MTConnect, izleme için salt okunur bir standarttır. Makineye komut göndermek, kontrol üreticisinin kendi arayüzlerini gerektirir.

İlgili yazılar

CODESYS MQTT Client: PLC Değişkenlerini Bir Broker'a Yayınlama

CODESYS IIoT MQTT Client kütüphanesini PLC değişkenlerini JSON olarak yayınlayacak şekilde yapılandırın, broker.connectmq.com üzerinde doğrulayın, ardından kimlik bilgileri ve TLS içeren özel bir broker'a geçin.

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.