Akıllı Üretim

MQTT ile Gerçek Zamanlı OEE Takibi: Canlı Bir OEE Servisi Kurun

Gerçek zamanlı OEE takibi için uygulamalı bir rehber: makineler durum ve sayaçları MQTT ile yayınlar, bir Python servisi her dakika kullanılabilirlik, performans ve kaliteyi hesaplar ve canlı OEE'yi herhangi bir dashboard için yayınlar.

Makinelerin durum ve sayaçlarını MQTT ile canlı bir OEE göstergesini güncelleyen bir servise yayınladığı gerçek zamanlı OEE takibi görseli
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

Gerçek zamanlı OEE takibi, vardiya sonu tablosunun yerine, harekete geçmek için hâlâ zaman varken her dakika güncellenen bir sayı koyar. Bu rehberde tüm hattı kuracaksınız: makineler durumlarını ve sayaçlarını MQTT ile yayınlar, bir Python servisi mevcut vardiya için kullanılabilirlik, performans ve kaliteyi hesaplar ve sonuç herhangi bir dashboard'un göstermesi için broker'a geri yayınlanır. Her parçayı canlı bir broker'a karşı bir dizüstü bilgisayarda çalıştırabilirsiniz.

Gerçek Zamanlı OEE Neden Vardiya Sonu Raporlarından Üstündür

Bir vardiya raporu size dün neyin yanlış gittiğini söyler. O noktada vardiya bitmiş, operatörler eve gitmiş ve sebepler yarı yarıya unutulmuştur. Hatta gösterilen canlı bir OEE değeri, vardiya amirinin bir arızadan sonra kullanılabilirliğin düştüğünü görmesini, hız düşürüldüğünde performansın gerilediğini fark etmesini ve aynı kişiler ve koşullar hâlâ oradayken tepki vermesini sağlar.

Otomatik hesaplama, girdiler hakkındaki tartışmaları da ortadan kaldırır. Durumlar ve sayaçlar doğrudan makineden geldiğinde sayı operatörler, amirler ve yöneticiler için aynıdır; tartışmalar "sayı doğru mu?" sorusundan "bu konuda ne yapacağız?" sorusuna geçer.

Mimari

[Machine / PLC gateway] --state, counts--> [MQTT broker] --> [OEE service] --oee--> [MQTT broker] --> [Dashboards, andon, historian]

Her bileşen yalnızca broker ile konuşur. Makineler OEE servisinin varlığından haberdar değildir; dashboard'lar da verinin nereden geldiğini bilmez. Bu ayrıştırma, bir broker kullanmanın ana sebebidir; kalıp size yeniyse önce bir MQTT broker'ın ne yaptığını okuyun.

Tek bir makine için topic'ler:

Topic Payload Yayınlanma
.../line2/filler/state {"state": "RUNNING", "ts": ...} Her değişiklikte, retained
.../line2/filler/counts {"total": 1234, "reject": 12, "ts": ...} 10 saniyede bir, kümülatif
.../line2/filler/config {"ideal_cycle_s": 1.0, "shift_start": ...} Değişiklikte, retained
.../line2/filler/oee {"availability": ..., "oee": ...} Servis tarafından 60 saniyede bir, retained

Durumlar RUNNING, DOWN, IDLE, SETUP ve PLANNED_STOP'tur. Planlı duruşlar planlı üretim süresinden çıkarılır; diğer tüm çalışmayan durumlar kullanılabilirlik kaybı sayılır. Formül ayrıntıları ve uç durumlar OEE nasıl hesaplanır yazısında ele alınır.

Adım 1: Bir Makineyi Simüle Edin

Geliştirme için genel MQTT test broker'ını kullanın. Genel alan herkese açık olduğu için topic önekinize rastgele bir kimlik seçin.

# machine_sim.py
import json
import random
import time

import paho.mqtt.client as mqtt

BASE = "connectmq/demo/q8n3d1/plant1/line2/filler"
IDEAL_CYCLE_S = 1.0

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="filler-sim-q8n3d1")
client.connect("broker.connectmq.com", 1883, keepalive=30)
client.loop_start()

shift_start = time.time()
client.publish(f"{BASE}/config", json.dumps({"ideal_cycle_s": IDEAL_CYCLE_S, "shift_start": shift_start}), qos=1, retain=True)

state, total, reject = "RUNNING", 0, 0
client.publish(f"{BASE}/state", json.dumps({"state": state, "ts": time.time()}), qos=1, retain=True)

while True:
    # Rastgele durum değişiklikleri
    if state == "RUNNING" and random.random() < 0.02:
        state = random.choice(["DOWN", "IDLE", "SETUP"])
        client.publish(f"{BASE}/state", json.dumps({"state": state, "ts": time.time()}), qos=1, retain=True)
    elif state != "RUNNING" and random.random() < 0.2:
        state = "RUNNING"
        client.publish(f"{BASE}/state", json.dumps({"state": state, "ts": time.time()}), qos=1, retain=True)

    if state == "RUNNING":
        made = int(10 / IDEAL_CYCLE_S * random.uniform(0.8, 0.98))
        total += made
        reject += sum(1 for _ in range(made) if random.random() < 0.02)

    client.publish(f"{BASE}/counts", json.dumps({"total": total, "reject": reject, "ts": time.time()}), qos=1)
    time.sleep(10)

Adım 2: Gerçek Zamanlı OEE Takip Servisini Oluşturun

Servis, hattaki her makineye wildcard'larla abone olur, mevcut vardiyanın durum geçmişini tutar ve her 60 saniyede bir yeniden hesaplar. Makine adı topic'ten alındığı için aynı anda birkaç makineyi yönetir.

# oee_service.py
import json
import threading
import time
from collections import defaultdict

import paho.mqtt.client as mqtt

LINE = "connectmq/demo/q8n3d1/plant1/line2"
INTERVAL_S = 60

machines = defaultdict(lambda: {
    "events": [],          # (ts, state) listesi
    "total": 0, "reject": 0,
    "ideal_cycle_s": None, "shift_start": None,
})
lock = threading.Lock()


def on_connect(client, userdata, flags, reason_code, properties):
    print("Connected:", reason_code)
    client.subscribe([(f"{LINE}/+/state", 1), (f"{LINE}/+/counts", 1), (f"{LINE}/+/config", 1)])


def on_message(client, userdata, msg):
    parts = msg.topic.split("/")
    machine, kind = parts[-2], parts[-1]
    data = json.loads(msg.payload)
    with lock:
        m = machines[machine]
        if kind == "config":
            m["ideal_cycle_s"] = data["ideal_cycle_s"]
            if m["shift_start"] != data["shift_start"]:
                m["shift_start"] = data["shift_start"]
                # Mevcut durumu yeni vardiyaya taşı, eski geçmişi at
                m["events"] = [(data["shift_start"], m["events"][-1][1])] if m["events"] else []
        elif kind == "state":
            m["events"].append((data["ts"], data["state"]))
        elif kind == "counts":
            m["total"], m["reject"] = data["total"], data["reject"]


def calculate(m, now):
    start = m["shift_start"]
    events = sorted(e for e in m["events"] if e[0] <= now)
    run = planned_stop = 0.0
    for i, (ts, state) in enumerate(events):
        seg_start = max(ts, start)
        seg_end = events[i + 1][0] if i + 1 < len(events) else now
        if seg_end <= seg_start:
            continue
        if state == "RUNNING":
            run += seg_end - seg_start
        elif state == "PLANNED_STOP":
            planned_stop += seg_end - seg_start
    planned = (now - start) - planned_stop
    total, reject = m["total"], m["reject"]
    a = run / planned if planned > 0 else 0.0
    p = min(m["ideal_cycle_s"] * total / run, 1.0) if run > 0 else 0.0
    q = (total - reject) / total if total > 0 else 0.0
    return {
        "availability": round(a, 4), "performance": round(p, 4), "quality": round(q, 4),
        "oee": round(a * p * q, 4), "run_min": round(run / 60, 1),
        "planned_min": round(planned / 60, 1), "good": total - reject, "ts": now,
    }


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="oee-service-q8n3d1")
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 1883, keepalive=30)
client.loop_start()

while True:
    time.sleep(INTERVAL_S)
    now = time.time()
    with lock:
        ready = {k: v for k, v in machines.items() if v["shift_start"] and v["ideal_cycle_s"]}
        results = {k: calculate(v, now) for k, v in ready.items()}
    for machine, result in results.items():
        client.publish(f"{LINE}/{machine}/oee", json.dumps(result), qos=1, retain=True)
        print(machine, result)

Simülatörü bir terminalde, servisi başka bir terminalde çalıştırın. Bir dakika sonra OEE değerlerinin yazdırıldığını ve yayınlandığını göreceksiniz. Bunları üçüncü bir terminalden izleyin:

mosquitto_sub -h broker.connectmq.com -p 1883 -i oee-viewer-q8n3d1 -t "connectmq/demo/q8n3d1/plant1/line2/+/oee" -v

Tasarım Gerçek Dünya Sorunlarını Nasıl Ele Alır

Servisin yeniden başlatılması. Durum ve yapılandırma retained olduğu için yeniden başlatılan servis, her makinenin güncel durumunu ve vardiya başlangıcını hemen alır. Önceki durum değişikliklerinin geçmişini kaybeder; bu yüzden kullanılabilirlik bir sonraki vardiyaya kadar yaklaşık değerdir. Üretimde olayları küçük bir veritabanına kaydedin veya açılışta bir historian'dan yeniden oluşturun.

Kaybolan mesajlar. Sayaçlar kümülatif olduğundan kaybolan bir sayaç mesajı yalnızca güncellemeyi geciktirir. Durum mesajları QoS 1 kullanır, böylece broker bunları onaylar.

Vardiya değişimi. Makine gateway'i (veya bir MES) yeni shift_start değeriyle yeni bir config yayınlar. Servis o makinenin geçmişini otomatik olarak sıfırlar. Sayaçlar da aynı anda sıfırlanmalıdır.

Saat kayması. Tüm zaman damgaları uçtan (edge) gelir. Gateway'leri NTP ile senkron tutun; aksi halde saati bir dakika ileri olan bir gateway negatif veya şişirilmiş süreler üretir.

Yüzde 100'ün üzerinde performans. Üst sınır, hatalı bir ideal çevrim süresini gizler. Tetiklendiğinde bir uyarı loglayın ve ana verileri düzeltin.

Canlı OEE'yi Göstermek

MQTT destekli her ekran oee topic'lerine abone olabilir. İyi çalışan seçenekler:

  1. OEE için bir gösterge ve A, P ve Q için üç çubukla Node-RED Dashboard 2.0. Node-RED OEE dashboard'u rehberi bunu adım adım anlatır.
  2. Üretim hattı izleme dashboard'u rehberindeki gibi, canlı değerin yanında vardiya geçmişi için Telegraf ve InfluxDB ile beslenen Grafana.
  3. Hiç backend gerektirmeyen, wss://broker.connectmq.com:8084/mqtt üzerinden MQTT.js kullanan bir tarayıcı sayfası.

Yalnızca OEE'yi değil, üç faktörü de gösterin. Kullanılabilirliği yüzde 95, performansı yüzde 70 gören bir amir, arızalara değil hıza ve mikro duruşlara bakması gerektiğini bilir. Uzun duruşlara sebepleri tazeyken atanabilmesi için canlı sayıyı makine duruş takibi ile eşleştirin.

Hedefler ve Alarmlar Eklemek

Canlı bir OEE sayısı bir şeyle karşılaştırıldığında daha faydalı hale gelir. İki eklemeyi erkenden yapmaya değer.

Vardiya hedefi takibi. Vardiya için bir hedef adedi config topic'ine yayınlayın ve servisin her sonuca expected_now ve gap eklemesine izin verin: hattın vardiyanın bu noktasında ulaşmış olması gereken adet ve gerçekleşenle farkı. Operatörler "OEE yüzde 71" yerine "340 adet gerideyiz" ifadesine çok daha fazla tepki verir ve her iki sayı da aynı veriden gelir.

Eşik alarmları. Hangi koşulların bir kişinin müdahalesini gerektirdiğine karar verin; örneğin son bir saatte kullanılabilirliğin yüzde 80'in altında olması veya bir makinenin on dakikadan uzun süre DOWN durumunda kalması. Bunları uygulamanın iki basit yolu vardır:

  1. OEE servisinin bir kural tetiklendiğinde bir alert mesajı yayınlamasını sağlayın ve bir Node-RED akışı, andon ışığı veya mesajlaşma entegrasyonunun buna abone olmasını sağlayın.
  2. Yayınlanan oee topic'leri üzerinde ConnectMQ portalındaki eşik alarm kurallarını kullanın; her tetikleme ek kod gerektirmeden alarm kaydına işlenir.

Kural listesini kısa tutun. Bir vardiyada birkaç kez çalan ve kimsenin üzerine bir şey yapmadığı alarmlar ayarlanmalı veya kaldırılmalıdır; aksi halde insanlar hepsini okumayı bırakır.

Kayan pencereler. Vardiya başından bu yana olan sayının yanında son 60 dakikanın OEE'sini de hesaplayın. Vardiya başından bu yana olan değerler vardiyanın sonlarına doğru yavaş değişir ve yeni bir sorunu gizleyebilir; kayan bir saat bunu hemen gösterir. Vardiya başlangıcı yerine bir saat önceki bir pencere başlangıcı verirseniz aynı calculate fonksiyonu çalışır.

Üretime Geçiş

Gerçek makineleri bağlamadan önce genel broker'dan ayrılın. ConnectMQ ile portalda özel bir broker oluşturur ve her istemci için bir kullanıcı adı, parola ve client ID alırsınız. Her iki betikteki bağlantıyı değiştirin:

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="YOUR_CLIENT_ID")
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set()  # sistem CA deposu Let's Encrypt sertifikasını doğrular
client.connect("broker.connectmq.com", 8883, keepalive=30)

Tam yönetilen bir MQTT servisi, broker bakımını tesis ekibinin üzerinden alır ve portalın canlı topic gezgini, servisi ayıklamaya başlamadan önce her makinenin yayın yapıp yapmadığını gösterir. Büyük resim için akıllı üretim rehberini okuyun.

OEE Servisinizi ConnectMQ Üzerinde Çalıştırın

app.connectmq.com adresinde kredi kartı olmadan Serverless planında ücretsiz bir broker oluşturun, gateway'lerinizi ve OEE servisini ona yönlendirin ve canlı OEE'yi bugün hat ekranına taşıyın.

Sık Sorulan Sorular

Gerçek zamanlı OEE ne sıklıkla yeniden hesaplanmalı?

Dakikada bir iyi bir varsayılandır. Saha için yeterince hızlı tepki verir ve her sayaç mesajıyla zıplayan bir sayıdan kaçınır.

OEE hesaplaması nerede çalışmalı?

Sonucu broker'a yayınlayan tek bir serviste; böylece her dashboard aynı değeri gösterir. Her dashboard'da biraz farklı mantıkla yeniden hesaplamaktan kaçının.

Bu yapı birkaç makineyi ve hattı yönetebilir mi?

Evet. Servis wildcard abonelikler kullanır ve her şeyi topic'ten alınan makine adına göre tutar. Birkaç hattı kapsamak için wildcard'a bir seviye ekleyin.

Bir makine yayın yapmayı bırakırsa ne olur?

Son retained durumu broker'da kalır. Gateway'e OFFLINE yayınlayan bir Last Will mesajı ekleyin; böylece servis sessizliği "çalışıyor" yerine "bilinmiyor" olarak değerlendirebilir.

İlgili yazılar

OEE vs TEEP vs OOE: Hangi Metriği Kullanmalısınız?

OEE, OOE ve TEEP aynı performans ve kalite faktörlerini paylaşır, ancak farklı zaman tabanlarına göre ölçer. Bu karşılaştırma tek bir örnek üzerinden ilerliyor ve her metriğin ihtiyaç duyduğu MQTT sinyallerini listeliyor.

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.