Node-RED

MQTT Makine Verileriyle Node-RED OEE Paneli

Node-RED'de iki MQTT topic'inden, makine durumu ve parça sayaçlarından OEE hesaplayın; ardından kullanılabilirlik, performans, kalite ve OEE değerlerini Dashboard 2.0 göstergelerinde gösterin ve KPI'ları diğer sistemler için yeniden yayınlayın.

MQTT makine verileriyle beslenen kullanılabilirlik, performans, kalite ve OEE için dört göstergeli Node-RED OEE paneli
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

Bir Node-RED OEE paneli, bir MES satın almadan gerçek bir üretim KPI'ını ekibin önüne koymanın en hızlı yollarından biridir. Bu rehberde iki MQTT topic'inden, makine durumu ve parça sayaçlarından kullanılabilirlik, performans ve kaliteyi hesaplayacak ve canlı OEE'yi Dashboard 2.0 göstergelerinde göstereceksiniz. Ayrıca KPI'ları diğer araçların kullanabilmesi için MQTT'ye yeniden yayınlayacak ve basit OEE hesaplarını yanıltan uç durumları öğreneceksiniz.

Bir Dakikada OEE

Toplam Ekipman Etkinliği (Overall Equipment Effectiveness), her biri 0 ile 1 arasında olan üç oranı çarpar:

Faktör Formül Neyi kaybeder
Kullanılabilirlik Çalışma süresi / planlı üretim süresi Arızalar, ürün değişimleri, malzeme beklemesi
Performans (İdeal çevrim süresi x toplam adet) / çalışma süresi Yavaş çevrimler, mikro duruşlar
Kalite Sağlam adet / toplam adet Hurda ve yeniden işleme
OEE Kullanılabilirlik x Performans x Kalite Yukarıdakilerin tümü

Formülün güzelliği çok az veri gerektirmesidir: makinenin ne zaman çalıştığı, kaç parça ürettiği ve bunların kaçının sağlam olduğu. Bu, MQTT'ye düzgün biçimde oturur. Planlı ve plansız duruşlar dahil tanımlara daha ayrıntılı bakmak için OEE nasıl hesaplanır yazısına göz atın.

MQTT Veri Modeli

Makine ya da önündeki bir gateway iki topic yayınlar:

Topic Payload Retained Ne zaman
connectmq/demo/a7f3k2/plant1/line1/press1/state RUNNING, IDLE veya DOWN Evet Her değişiklikte
connectmq/demo/a7f3k2/plant1/line1/press1/count {"total": 1234, "good": 1201} Hayır Birkaç saniyede bir

İki tasarım tercihi bu yapıyı sağlam kılar:

  • Durum olay güdümlüdür ve retained'dır. Node-RED bağlandıktan hemen sonra mevcut durumu öğrenir ve çalışma süresini değişiklik olaylarından biriktirir.
  • Sayaçlar parça başına değil, kümülatiftir. Bir mesaj kaybolursa bir sonraki mesaj yine doğru toplamı taşır. Node-RED farkları hesaplar ve geriye giden bir sayaç, negatif üretim yerine PLC sıfırlaması olarak değerlendirilir.

Topic, bir demo önekinin arkasında ISA-95 tarzı bir hiyerarşiyi (tesis, hat, makine) izler. Herkese açık broker'ı herkes okuyabildiği için a7f3k2 yerine kendi rastgele dizenizi kullanın.

Bir Makineyi Simüle Edin

Bu Python betiği, 2 saniyelik ideal çevrimi, ara sıra duruşları ve yaklaşık yüzde 3 hurdası olan bir pres gibi davranır. Herkese açık MQTT test broker'ı olan broker.connectmq.com adresine yayın yapar.

# pip install "paho-mqtt>=2.0"
import json
import random
import time
import uuid

import paho.mqtt.client as mqtt

BASE = "connectmq/demo/a7f3k2/plant1/line1/press1"

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=f"press-sim-{uuid.uuid4().hex[:8]}")
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_start()

state = None
total = 0
good = 0
next_cycle = time.time()
last_count_pub = 0.0


def set_state(new_state):
    global state
    if new_state != state:
        state = new_state
        client.publish(f"{BASE}/state", state, qos=1, retain=True)
        print("State:", state)


set_state("RUNNING")
try:
    while True:
        now = time.time()
        if state == "RUNNING":
            if random.random() < 0.004:
                set_state(random.choice(["IDLE", "DOWN"]))
            elif now >= next_cycle:
                total += 1
                if random.random() > 0.03:
                    good += 1
                # Gerçek çevrimler idealden biraz daha yavaştır
                next_cycle = now + random.uniform(2.0, 2.6)
        elif random.random() < 0.02:
            set_state("RUNNING")
            next_cycle = time.time() + 2.0

        if now - last_count_pub >= 5:
            client.publish(f"{BASE}/count",
                           json.dumps({"total": total, "good": good}), qos=1)
            last_count_pub = now
        time.sleep(0.2)
except KeyboardInterrupt:
    pass
finally:
    client.loop_stop()
    client.disconnect()

Node-RED OEE Paneli Akışını Oluşturun

Dashboard 2.0 (@flowfuse/node-red-dashboard) kurulu Node-RED 4.x gerekir. Henüz kullanmadıysanız Dashboard 2.0 rehberi kurulumu ve sayfa ile grup yapısını anlatır.

Girişler

  1. .../press1/state üzerinde, çıktısı "a UTF-8 string" olan bir mqtt in node'u.
  2. .../press1/count üzerinde, çıktısı "a parsed JSON object" olan bir mqtt in node'u.
  3. Her 5 saniyede bir tekrarlanan ve msg.topic değeri tick olan "tick" adlı bir inject node'u.
  4. msg.topic değeri shift/reset olan "Start new shift" etiketli bir ui-button ile birlikte, aynı topic'e sahip ve vardiya değişim saatlerinize (örneğin 06:00, 14:00 ve 22:00) zamanlanmış bir inject node'u.

press1/# wildcard'ı yerine iki ayrı abonelik kullanın. Daha sonra KPI'ları aynı makine yolu altında yayınlayacaksınız ve bir wildcard kendi çıktınızı hesaplamaya geri besler.

OEE hesaplaması

Dört girişin tümünü beş çıkışlı tek bir function node'una bağlayın:

// Function node "OEE calculator" - Outputs değerini 5 yapın
const IDEAL_CYCLE_S = 2.0;         // bu makine için parça başına ideal saniye
const now = Date.now();

function newShift() {
    return { shiftStart: now, state: "UNKNOWN", since: now, runMs: 0,
             lastTotal: null, lastGood: null, total: 0, good: 0 };
}

let s = flow.get("oee") || newShift();
const topic = String(msg.topic || "");

if (topic === "shift/reset") {
    const keepState = s.state;
    s = newShift();
    s.state = keepState;            // makine hâlâ aynı durumda
    flow.set("oee", s);
    return null;
}

if (topic.endsWith("/state")) {
    const st = String(msg.payload).trim().toUpperCase();
    if (s.state === "RUNNING") s.runMs += now - s.since;
    s.state = st;
    s.since = now;
    flow.set("oee", s);
    return null;
}

if (topic.endsWith("/count")) {
    const total = Number(msg.payload.total);
    const good = Number(msg.payload.good);
    if (!Number.isFinite(total) || !Number.isFinite(good)) return null;
    if (s.lastTotal !== null) {
        // Geriye giden bir sayaç, PLC'nin onu sıfırladığı anlamına gelir
        const dTotal = total >= s.lastTotal ? total - s.lastTotal : total;
        const dGood = good >= s.lastGood ? good - s.lastGood : good;
        s.total += dTotal;
        s.good += Math.min(dGood, dTotal);
    }
    s.lastTotal = total;
    s.lastGood = good;
    flow.set("oee", s);
    return null;
}

if (topic !== "tick") return null;

// Vardiyanın şu ana kadarki KPI'larını hesapla
const runMs = s.runMs + (s.state === "RUNNING" ? now - s.since : 0);
const plannedMs = now - s.shiftStart;
const availability = plannedMs > 0 ? runMs / plannedMs : 0;
const rawPerformance = runMs > 0 ? (IDEAL_CYCLE_S * 1000 * s.total) / runMs : 0;
const performance = Math.min(1, rawPerformance);
const quality = s.total > 0 ? s.good / s.total : 0;
const oee = availability * performance * quality;

if (rawPerformance > 1.05) {
    node.warn("Performance above 100%: check IDEAL_CYCLE_S");
}

const pct = v => Math.round(v * 1000) / 10;
node.status({ fill: s.state === "RUNNING" ? "green" : "red", shape: "dot",
              text: `${s.state} OEE ${pct(oee)}%` });

return [
    { payload: pct(availability) },
    { payload: pct(performance) },
    { payload: pct(quality) },
    { payload: pct(oee) },
    { topic: "connectmq/demo/a7f3k2/plant1/line1/press1/oee",
      payload: { availability: pct(availability), performance: pct(performance),
                 quality: pct(quality), oee: pct(oee), total: s.total, good: s.good,
                 state: s.state, shiftStart: new Date(s.shiftStart).toISOString() },
      retain: true }
];

Vardiyanın bilinen bir andan başlaması için deploy ettikten sonra bir kez Start new shift düğmesine tıklayın.

Widget'lar

  • 1'den 4'e kadar olan çıkışlar, aralığı 0 ile 100, birimi % olan dört ui-gauge node'una gider. OEE için yaygın bir renk şeması 60'ın altında kırmızı, 60 ile 85 arasında sarı ve 85'in üstünde yeşildir; ancak kendi başlangıç seviyenizi yansıtan aralıklar seçin.
    1. çıkış, topic ve retain alanları boş bırakılmış bir mqtt out node'una gider; böylece mesajdaki msg.topic ve msg.retain değerlerini kullanır. Makine durumunu da ekranda görmek istiyorsanız payload.state değerini çıkaran bir change node'unun arkasına bir ui-text node'u ekleyin.

/dashboard adresini açın ve ilk birkaç dakikada sayıların oturmasını izleyin. Vardiyanın başında tek bir duruş kullanılabilirliği büyük ölçüde dalgalandırır; bu matematiksel olarak doğrudur ve operatörler buna çabuk alışır.

OEE'yi Bozan Tuzaklar

  1. Yanlış ideal çevrim süresi. Performans yüzde 100'ün üzerinde duruyorsa ideal çevriminiz fazla yavaş tanımlanmıştır. Sadece sınırlayıp geçmeyin; koddaki sınır bir veri sorununu gizler.
  2. Planlı duruşları arıza süresi olarak saymak. Molalar, planlı bakım ve sipariş olmayan dönemler genellikle planlı üretim süresinin dışında tutulur. Tesisiniz bu tanımı kullanıyorsa bir PLANNED_STOP durumu ekleyin ve bu süreyi plannedMs dışında bırakın.
  3. Yeniden başlatmalarda durumu kaybetmek. Flow context varsayılan olarak bellekte tutulur. Vardiya ortasındaki bir Node-RED yeniden başlatmasının KPI'ları sıfırlamaması için oee nesnesini dosya tabanlı bir context deposunda saklayın.
  4. Sırası bozuk mesajlar. Tek bir publisher ile QoS 1 üzerinden MQTT, topic başına sırayı korur; ancak state ve count ayrı topic'lerdir. Yukarıdaki gibi bir zamanlayıcıyla hesaplamak küçük zamanlama farklarını önemsiz kılar.
  5. Sayaç taşması. 16 bitlik PLC sayaçları 65.535'te başa döner. Sıfırlama mantığı bir taşmayı sıfırlama gibi ele alır; bu da en fazla bir aralıklık sayım kaybettirir.

Duruş nedenleri doğal bir sonraki adımdır: DOWN durumuna bir neden kodu ekleyin ve neden başına dakikaları biriktirin. Makine duruş takibi rehberi bu kodların nasıl yapılandırılacağını anlatır.

OEE Geçmişini Saklama

Göstergeler yalnızca mevcut vardiyayı gösterir. Vardiyaları karşılaştırmak için retained KPI mesajını her vardiya sonunda veya her dakika bir zaman serisi veritabanına yazın. Node-RED InfluxDB rehberi, tam olarak bu tür bir JSON'u hat ve makine gibi etiketlerle nasıl saklayacağınızı ve ardından grafiğe dökeceğinizi gösterir.

Tüm Hatta veya Tesise Ölçeklendirme

Makine başına bir function node'u bir pilot için yeterlidir. Tam bir hat için plant1/line1/+/state gibi tek seviyeli bir wildcard ile abone olun, topic seviyesiyle anahtarlanmış makine başına bir context nesnesi tutun ve her makinenin KPI'larını kendi topic'ine yayınlayın. Hesaplama yalnızca MQTT topic'lerine bağlı olduğundan, verinin bir PLC gateway'inden, bir ESP32 sayacından veya bir edge cihazından gelmesi fark etmez.

Broker'ın önemli olduğu yer de burasıdır. Düzinelerce makinenin, bir Node-RED sunucusunun, bir historian'ın ve belki bir SCADA istemcisinin aynı anda bağlı olduğu bir tesis, herkese açık bir test hizmeti yerine kimlik doğrulamalı güvenilir bir bulut MQTT broker'a ihtiyaç duyar. ConnectMQ, plant1/line1/press1/state gibi ISA-95 tarzı topic'leri tanır ve portalında cihazları bu seviyelere göre gruplar; bu da hangi makinelerin veri gönderdiğini görmeyi kolaylaştırır. ConnectMQ portalındaki eşik uyarı kuralları da seçtiğiniz bir sınırı aşan sayısal bir değeri işaretleyebilir; hesaplamanın kendisi ise Node-RED'in sorumluluğunda kalır. Bu altyapının hiçbirini kendiniz işletmek istemiyorsanız tam yönetilen bir MQTT hizmeti broker tarafını bakım listenizin dışında tutar. Broker ve Node-RED temelleri için Node-RED MQTT rehberiyle başlayın.

OEE Verilerinizi ConnectMQ'ya Taşıyın

app.connectmq.com adresinde kredi kartı gerektirmeyen ücretsiz Serverless planıyla kaydolun. Bir broker oluşturun, üretilen kullanıcı adı, parola ve client ID'yi makinelerinizde ve Node-RED'de kullanın ve port 8883 üzerinde TLS'e geçin. Bir sonraki vardiya değişiminden önce özel bir OEE hattınız çalışıyor olacak.

Sık Sorulan Sorular

Node-RED'de OEE hesaplamak için hangi verilere ihtiyacım var?

Zaman içindeki makine durumuna, toplam parça sayısına, sağlam parça sayısına ve ideal çevrim süresine ihtiyacınız var. Bu dört girdiyle Node-RED kullanılabilirliği, performansı, kaliteyi ve OEE'yi hesaplayabilir.

Makineler neden kümülatif sayaç yayınlamalı?

Kümülatif sayaçlar, her mesaj tam toplamı taşıdığı için hesaplamayı kaybolan veya geciken mesajlara karşı toleranslı hale getirir. Node-RED farkı hesaplar ve sıfırlamaları yönetir.

OEE paneli ne sıklıkla güncellenmeli?

Operatörler için 5 ila 30 saniyede bir yeterlidir. Her mesajda değil de bir zamanlayıcıyla hesaplamak, birçok makine aynı anda yayın yaptığında panelin akıcı kalmasını da sağlar.

Birden fazla makinenin OEE'sini tek sayfada gösterebilir miyim?

Evet. Wildcard aboneliği kullanın, makine başına bir context nesnesi tutun ve her makine için bir panel grubu ya da bir ui-template node'uyla oluşturulmuş bir tablo ekleyin.

İlgili yazılar

ISA-95 Topic'leriyle Node-RED OPC UA İstemcisinden MQTT'ye

Bir PLC veya simülasyon sunucusundaki OPC UA değişkenlerine node-red-contrib-opcua ile abone olun, node ID'lerini ISA-95 tarzı MQTT topic'lerine eşleyin ve değerleri kalite bilgisi ve zaman damgalarıyla yayınlayın.

8 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.