Zum Inhalt springen

OEE-Konnektor

Der OEE (Overall Equipment Effectiveness)-Konnektor berechnet die kanonische SEMI E10-Fertigungskennzahl aus kumulativen Produktionszählern, die im Eingangsstream eintreffen. Er gibt OEE pro Block plus die drei Komponentenmetriken (Verfügbarkeit, Leistung, Qualität) aus, damit sie als Anzeigen, Diagramme oder in einer Zeitreihendatenbank dargestellt werden können.

Konnektor-Typen:

  • OEE - Zustandsbehafteter Prozessor, der OEE in einem gleitenden Fenster oder pro Schicht berechnet

OEE wird wie folgt berechnet:

OEE = Verfügbarkeit × Leistung × Qualität

Wobei:

  • Verfügbarkeit = runTime / plannedProductionTime
  • Leistung = (idealCycleTime × totalCount) / runTime
  • Qualität = goodCount / totalCount

Alle drei werden auf [0, 1] begrenzt.

  • ✅ Zwei Fenstermodi: gleitend (zeitbasiert) und Schicht (HH:MM begrenzt)
  • ✅ Automatische Akkumulation, wenn RunTime / PlannedProductionTime vom Gerät nicht bereitgestellt werden
  • ✅ Akzeptiert running als boolean-ähnliches Statusfeld (true/false, 1/0, on/off, yes/no usw.)
  • ✅ Konfigurierbare Schwellenwerte (red, yellow) und target für die Anzeigegestaltung
  • ✅ Gibt eine N/A-Payload aus (oee.* weggelassen), wenn ein Fenster unzureichende Daten enthält
  • ✅ Block-ID-Namespacing, damit mehrere OEE-Instanzen in dieselbe Payload schreiben können
  • ✅ Tolerante numerische Parsing — Strings werden automatisch als Floats geparst
{
"type": "OEE",
"config": {
"fields": {
"plannedProductionTime": "planned_time_s",
"runTime": "run_time_s",
"idealCycleTime": "ideal_cycle_s",
"totalCount": "parts_total",
"goodCount": "parts_good"
},
"windowMode": "sliding",
"windowSeconds": 3600,
"thresholds": {
"red": 0.6,
"yellow": 0.8
},
"target": 0.85
}
}

Schichtfenster mit Status-Flag und literaler Zykluszeit

Abschnitt betitelt „Schichtfenster mit Status-Flag und literaler Zykluszeit“
{
"type": "OEE",
"config": {
"fields": {
"running": "machine_running",
"totalCount": "parts_total",
"goodCount": "parts_good"
},
"idealCycleTimeSeconds": 4.5,
"windowMode": "shift",
"shiftStart": "06:00",
"shiftEnd": "14:00",
"timezone": "Europe/Rome",
"thresholds": {
"red": 0.6,
"yellow": 0.8
},
"target": 0.85
}
}

Das fields-Objekt benennt die Payload-Schlüssel, die der Konnektor aus jedem eingehenden Sample liest.

{
"fields": {
"plannedProductionTime": "planned_time_s",
"runTime": "run_time_s",
"running": "machine_running",
"idealCycleTime": "ideal_cycle_s",
"totalCount": "parts_total",
"goodCount": "parts_good"
}
}
FeldErforderlich?Hinweise
plannedProductionTimeOptionalKumulative Sekunden. Wenn weggelassen, akkumuliert der Konnektor Echtzeitsekunden seit dem ersten Sample
runTimeEiner von runTime / running ist erforderlichKumulative Sekunden, in denen die Maschine gelaufen ist
runningEiner von runTime / running ist erforderlichBoolean-ähnlicher Status; intern integriert
idealCycleTimeEiner von idealCycleTime / idealCycleTimeSeconds ist erforderlichSekunden pro Teil bei idealer Geschwindigkeit
totalCountErforderlichKumulative Anzahl versuchter Teile
goodCountErforderlichKumulative Anzahl guter Teile

Wenn das Gerät keine ideale Zykluszeit veröffentlicht, können Sie sie als Konstante deklarieren:

{
"idealCycleTimeSeconds": 4.5
}

Dies schließt sich gegenseitig mit fields.idealCycleTime aus.

{
"windowMode": "sliding"
}
  • sliding - Berechnet Deltas über ein rollendes Zeitfenster der Länge windowSeconds
  • shift - Berechnet Deltas seit Beginn der aktuellen Schicht, definiert durch shiftStart, shiftEnd und optionale timezone
{
"windowSeconds": 3600
}

Erforderlich für windowMode: sliding. Muss > 0 sein.

Empfohlene Werte:

  • Echtzeit-Anzeige: 300-900 (5-15 Minuten)
  • Stundentrend: 3600 (1 Stunde)
  • Langfristige Glättung: 28800 (8 Stunden)

Erforderlich für windowMode: shift:

{
"shiftStart": "06:00",
"shiftEnd": "14:00",
"timezone": "Europe/Rome"
}
  • shiftStart / shiftEnd - HH:MM im 24-Stunden-Format
  • timezone - IANA-Zeitzonenkennung (z.B. Europe/Rome, America/New_York, Asia/Tokyo). Standardmäßig UTC, falls weggelassen
  • Nachtschichten werden unterstützt (z.B. 22:0006:00)

Stilhinweise, die zusammen mit den OEE-Werten ausgegeben werden, damit Dashboards Anzeigen konsistent einfärben können:

{
"thresholds": {
"red": 0.6,
"yellow": 0.8
},
"target": 0.85
}

Einschränkungen:

  • red < yellow (strikt)
  • 0 ≤ red, yellow ≤ 1
  • 0 ≤ target ≤ 1

Jede Ausgabe wird durch die Block-ID der OEE-Konnektor-Instanz mit einem Namespace versehen (von Meddle automatisch injiziert):

{
"oee.<blockId>": 0.78,
"availability.<blockId>": 0.92,
"performance.<blockId>": 0.95,
"quality.<blockId>": 0.89,
"red.<blockId>": 0.6,
"yellow.<blockId>": 0.8,
"target.<blockId>": 0.85
}

Wenn das Fenster noch nicht genug Daten enthält (z.B. weniger als zwei Snapshots im Sliding-Modus oder die Schicht hat gerade erst begonnen), werden die Schlüssel oee/availability/performance/quality weggelassen und nur die Anzeigen-Style-Schlüssel ausgegeben. Dies ist die N/A-Payload.

DataPayload (kumulative Zähler) → OEE → DataPayload (oee.<blockId>, usw.)

Beispiel (gleitendes Fenster, 60s):

Eingangsstream:

{ "planned_time_s": 0, "run_time_s": 0, "parts_total": 0, "parts_good": 0 }
{ "planned_time_s": 60, "run_time_s": 55, "parts_total": 12, "parts_good": 11 }
{ "planned_time_s": 120, "run_time_s": 110, "parts_total": 24, "parts_good": 22 }

Mit idealCycleTimeSeconds: 4.5, windowSeconds: 60:

Nach dem dritten Sample:

  • ΔPlanned = 60s, ΔRun = 55s, ΔTotal = 12, ΔGood = 11
  • A = 55/60 = 0,917
  • P = (4,5 × 12) / 55 = 0,982
  • Q = 11/12 = 0,917
  • OEE = 0,917 × 0,982 × 0,917 = 0,826

Ausgabe:

{
"oee.<blockId>": 0.826,
"availability.<blockId>": 0.917,
"performance.<blockId>": 0.982,
"quality.<blockId>": 0.917,
"red.<blockId>": 0.6,
"yellow.<blockId>": 0.8,
"target.<blockId>": 0.85
}

Am besten für Live-Bediener-Dashboards, bei denen die Anzeige auf aktuelle Aktivitäten reagiert:

{
"type": "OEE",
"config": {
"fields": {
"running": "is_running",
"totalCount": "cumulative_parts",
"goodCount": "cumulative_good"
},
"idealCycleTimeSeconds": 6.0,
"windowMode": "sliding",
"windowSeconds": 900,
"thresholds": { "red": 0.55, "yellow": 0.75 },
"target": 0.85
}
}
{
"type": "OEE",
"config": {
"fields": {
"plannedProductionTime": "shift_planned_s",
"runTime": "shift_run_s",
"idealCycleTime": "ideal_cycle_s",
"totalCount": "shift_parts_total",
"goodCount": "shift_parts_good"
},
"windowMode": "shift",
"shiftStart": "06:00",
"shiftEnd": "14:00",
"timezone": "Europe/Rome",
"thresholds": { "red": 0.6, "yellow": 0.8 },
"target": 0.85
}
}
{
"type": "OEE",
"config": {
"fields": {
"running": "running_flag",
"totalCount": "ct_total",
"goodCount": "ct_good"
},
"idealCycleTimeSeconds": 3.2,
"windowMode": "shift",
"shiftStart": "22:00",
"shiftEnd": "06:00",
"timezone": "America/New_York",
"thresholds": { "red": 0.5, "yellow": 0.75 },
"target": 0.8
}
}

Ausgabe enthält nur Anzeigen-Style-Felder (kein oee.*)

Abschnitt betitelt „Ausgabe enthält nur Anzeigen-Style-Felder (kein oee.*)“

Problem: Die N/A-Payload wird ausgegeben

Lösungen:

  1. Sliding-Modus: erfordert mindestens 2 Snapshots im Fenster. Warten Sie auf ein zweites Sample
  2. Shift-Modus: gibt N/A zurück, wenn die aktuelle Zeit außerhalb von [shiftStart, shiftEnd] liegt
  3. Shift-Modus-Start: das erste Sample innerhalb der Schicht etabliert die Baseline; OEE erscheint ab dem zweiten Sample

Problem: Ein Fehler wird gemeldet mit Deltas, die als 0 oder negativ gemeldet werden

Lösungen:

  1. Die Zähler müssen monoton steigend sein. Wenn das Gerät sie zurücksetzt (z.B. bei Schichtwechsel), umhüllen Sie die Eingabe mit einem Transform, um zuerst in Deltas zu konvertieren, oder teilen Sie die OEE-Instanz pro Schicht auf
  2. Bestätigen, dass die Feldnamen auf Werte ungleich Null abgebildet werden
  3. Wenn das Fenster sehr kurz ist (windowSeconds: 10) und die Linie im Leerlauf ist, können Deltas genau Null sein; erweitern Sie das Fenster

Problem: invalid value for "..."-Fehler

Lösungen:

  1. Werte müssen nicht-negative endliche Zahlen sein. NaN, Unendlich und Negative werden abgelehnt
  2. Strings werden nur toleriert, wenn sie sich als nicht-negativer endlicher Float parsen lassen
  3. Wenn Ihre Quelle Booleans für “running” ausgibt, stellen Sie sicher, dass das Feld running — nicht runTime — konfiguriert ist

Problem: Verdächtig perfekte OEE

Lösungen:

  1. Prüfen, ob idealCycleTime realistisch ist. Ein zu langsamer Idealwert lässt die Leistung ≥ 1 werden, was auf 1 begrenzt wird
  2. Überprüfen, ob runTime < plannedProductionTime. Wenn sie identisch sind, ist die Verfügbarkeit 1,0

Problem: Schichtanfänge/-enden sind um N Stunden versetzt

Lösungen:

  1. Setzen Sie timezone immer auf einen gültigen IANA-Namen
  2. Verwenden Sie keine Offset-Notationen wie +02:00 — sie werden abgelehnt

1. Wenn möglich, gerätegemeldete Zähler bevorzugen

Abschnitt betitelt „1. Wenn möglich, gerätegemeldete Zähler bevorzugen“

Wenn die SPS runTime und plannedProductionTime als kumulative Sekunden veröffentlicht, verwenden Sie diese direkt. Der interne Akkumulator ist ein Fallback für Geräte, die nur ein running-Flag veröffentlichen.

  • Bediener: 5-15 Minuten gleitendes Fenster
  • Vorgesetzte: Fenster pro Schicht
  • Führungskräfte: Aggregation pro Tag oder pro Woche (nachgelagert)

Die ISO-Definition ist “schnellste nachhaltige Zykluszeit”, nicht “Marketing-Broschüre”. Ein optimistischer Wert drückt die Leistung und unterverkauft die reale OEE.

4. Mit einem Filter oder Transform vorgelagert kombinieren

Abschnitt betitelt „4. Mit einem Filter oder Transform vorgelagert kombinieren“

Wenn Ihr Raw-Stream nicht zusammengehörige Payloads enthält, verwenden Sie Filter, um vor dem OEE-Block nur Zähler-Updates zu behalten.

Jede OEE-Konnektor-Instanz wird durch blockId mit einem Namespace versehen, sodass Multi-Maschinen-Dashboards in einem einzigen Meddle-Flow koexistieren können.

ModbusReader (Maschine 1) ──┐
ModbusReader (Maschine 2) ──┼─→ Merge → Reshape → OEE → Chart (Anzeige)
ModbusReader (Maschine 3) ──┘ └→ InfluxDb2Writer
  1. ModbusReader (×N): Holt Zähler von jeder Maschine
  2. Merge: Kombiniert Payloads gekennzeichnet nach Maschinen-ID
  3. Reshape: Normalisiert Feldnamen, um der OEE-Konfiguration zu entsprechen
  4. OEE: Berechnet OEE pro Maschineninstanz
  5. Chart: Rendert die Anzeige mit red-, yellow-, target-Styling
  6. InfluxDb2Writer: Persistiert OEE für historisches Trending
OpcuaReader → OEE → Isa182 (Alarm bei OEE < 0.5) → Alert (E-Mail)

Löst eine Benachrichtigung aus, wenn anhaltende OEE unter 50% fällt — nützlich für die Erkennung chronischer Unterperformance.

  • Chart - Anzeige aus OEE-Ausgabe rendern
  • ISA-18.2 - Alarme bei niedriger OEE auslösen
  • Reshape - Zählerfeldnamen normalisieren
  • InfluxDB - OEE für Trending persistieren
  • Transform - Deltas aus nicht-monotonen Zählern berechnen