Salta ai contenuti

Connettore OEE

Il connettore OEE (Overall Equipment Effectiveness) calcola il KPI canonico SEMI E10 per la produzione partendo da contatori cumulativi di produzione che arrivano sullo stream di input. Emette l’OEE per blocco più le tre metriche componenti (Disponibilità, Prestazioni, Qualità) in modo che possano essere visualizzate come gauge, grafici o archiviate in un database time-series.

Tipi Connettore:

  • OEE - Processore con stato che calcola l’OEE su una finestra mobile o per turno

L’OEE è calcolato come:

OEE = Disponibilità × Prestazioni × Qualità

Dove:

  • Disponibilità = runTime / plannedProductionTime
  • Prestazioni = (idealCycleTime × totalCount) / runTime
  • Qualità = goodCount / totalCount

Tutti e tre sono limitati a [0, 1].

  • ✅ Due modalità di finestra: sliding (basata sul tempo) e shift (delimitata HH:MM)
  • ✅ Accumulazione automatica quando RunTime / PlannedProductionTime non sono forniti dal dispositivo
  • ✅ Accetta running come campo di stato booleano (true/false, 1/0, on/off, yes/no, ecc.)
  • ✅ Soglie configurabili (red, yellow) e target per lo stile del gauge
  • ✅ Emette payload N/A (oee.* omesso) quando una finestra ha dati insufficienti
  • ✅ Spaziatura ID per blocco in modo che più istanze OEE possano scrivere sullo stesso payload
  • ✅ Parsing numerico tollerante — le stringhe vengono interpretate automaticamente come float

Finestra Mobile con Contatori Riportati dal Dispositivo

Sezione intitolata “Finestra Mobile con Contatori Riportati dal Dispositivo”
{
"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
}
}

Finestra di Turno con Flag di Stato e Cycle Time Letterale

Sezione intitolata “Finestra di Turno con Flag di Stato e Cycle Time Letterale”
{
"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
}
}

L’oggetto fields nomina le chiavi del payload che il connettore legge da ogni campione in ingresso.

{
"fields": {
"plannedProductionTime": "planned_time_s",
"runTime": "run_time_s",
"running": "machine_running",
"idealCycleTime": "ideal_cycle_s",
"totalCount": "parts_total",
"goodCount": "parts_good"
}
}
CampoRichiesto?Note
plannedProductionTimeOpzionaleSecondi cumulativi. Se omesso, il connettore accumula secondi reali dal primo campione
runTimeUno tra runTime / running è richiestoSecondi cumulativi durante i quali la macchina era in esecuzione
runningUno tra runTime / running è richiestoStato booleano; integrato internamente
idealCycleTimeUno tra idealCycleTime / idealCycleTimeSeconds è richiestoSecondi per pezzo alla velocità ideale
totalCountRichiestoConteggio cumulativo dei pezzi tentati
goodCountRichiestoConteggio cumulativo dei pezzi buoni

Quando il dispositivo non pubblica l’ideal cycle time, puoi dichiararlo come costante:

{
"idealCycleTimeSeconds": 4.5
}

È mutuamente esclusivo con fields.idealCycleTime.

{
"windowMode": "sliding"
}
  • sliding - Calcola delta su una finestra temporale mobile di lunghezza windowSeconds
  • shift - Calcola delta dall’inizio del turno corrente, definito da shiftStart, shiftEnd e timezone opzionale
{
"windowSeconds": 3600
}

Richiesto per windowMode: sliding. Deve essere > 0.

Valori raccomandati:

  • Gauge realtime: 300-900 (5-15 minuti)
  • Trend ora per ora: 3600 (1 ora)
  • Smoothing a lungo termine: 28800 (8 ore)

Richiesta per windowMode: shift:

{
"shiftStart": "06:00",
"shiftEnd": "14:00",
"timezone": "Europe/Rome"
}
  • shiftStart / shiftEnd - Formato HH:MM a 24 ore
  • timezone - Identificatore IANA di timezone (es. Europe/Rome, America/New_York, Asia/Tokyo). Default UTC se omesso
  • I turni notturni sono supportati (es. 22:0006:00)

Suggerimenti di stile emessi insieme ai valori OEE in modo che le dashboard possano colorare i gauge in modo coerente:

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

Vincoli:

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

Ogni output è namespaced dal block ID dell’istanza del connettore OEE (auto-iniettato da Meddle):

{
"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
}

Quando la finestra non ha ancora dati sufficienti (es. meno di due snapshot in modalità sliding, o il turno è appena iniziato), le chiavi oee/availability/performance/quality vengono omesse e vengono emesse solo le chiavi di styling del gauge. Questo è il payload N/A.

DataPayload (contatori cumulativi) → OEE → DataPayload (oee.<blockId>, ecc.)

Esempio (finestra mobile, 60s):

Stream di input:

{ "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 }

Con idealCycleTimeSeconds: 4.5, windowSeconds: 60:

Dopo il terzo campione:

  • Δ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

Output:

{
"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
}

Ideale per dashboard operatore live dove il gauge risponde all’attività recente:

{
"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
}
}

Output Ha Solo Campi di Styling del Gauge (Nessun oee.*)

Sezione intitolata “Output Ha Solo Campi di Styling del Gauge (Nessun oee.*)”

Problema: Il payload N/A viene emesso

Soluzioni:

  1. Modalità sliding: richiede almeno 2 snapshot nella finestra. Attendi un secondo campione
  2. Modalità shift: restituisce N/A quando l’orario corrente è fuori da [shiftStart, shiftEnd]
  3. Avvio in modalità shift: il primo campione all’interno del turno stabilisce la baseline; l’OEE apparirà dal secondo campione in poi

Problema: Viene riportato un errore con delta riportati come 0 o negativi

Soluzioni:

  1. I contatori devono essere monotonicamente crescenti. Se il dispositivo li resetta (es. al cambio turno), avvolgi l’input in un Transform per convertirli in delta prima, oppure dividi l’istanza OEE per turno
  2. Conferma che i nomi dei campi mappino a valori non zero
  3. Se la finestra è molto breve (windowSeconds: 10) e la linea è inattiva, i delta possono essere esattamente zero; allarga la finestra

Problema: Errori invalid value for "..."

Soluzioni:

  1. I valori devono essere numeri finiti non negativi. NaN, infinity e negativi vengono rifiutati
  2. Le stringhe sono tollerate solo se vengono interpretate come un float finito non negativo
  3. Se la sorgente emette booleani per “running”, assicurati che sia configurato il campo running — non runTime

Problema: OEE sospettosamente perfetto

Soluzioni:

  1. Controlla che idealCycleTime sia realistico. Un ideale eccessivamente lento rende Prestazioni ≥ 1, che viene limitato a 1
  2. Verifica che runTime < plannedProductionTime. Se sono identici, la Disponibilità è 1.0

Problema: Gli inizi/fine turno sono sfasati di N ore

Soluzioni:

  1. Imposta sempre timezone su un nome IANA valido
  2. Non usare notazioni di offset come +02:00 — vengono rifiutate

1. Preferisci i Contatori Riportati dal Dispositivo Quando Disponibili

Sezione intitolata “1. Preferisci i Contatori Riportati dal Dispositivo Quando Disponibili”

Se il PLC pubblica runTime e plannedProductionTime come secondi cumulativi, usali direttamente. L’accumulatore interno è un fallback per dispositivi che pubblicano solo un flag running.

  • Operatori: finestra mobile di 5-15 minuti
  • Supervisori: finestra per turno
  • Dirigenti: aggregazione per giorno o settimana (a valle)

La definizione ISO è “tempo ciclo più veloce sostenibile”, non “brochure di marketing”. Un valore ottimistico deprime le Prestazioni e svaluta l’OEE reale.

Se il tuo stream raw contiene payload non correlati, usa Filter per mantenere solo gli aggiornamenti dei contatori prima del blocco OEE.

Ogni istanza del connettore OEE è namespaced dal blockId, quindi dashboard multi-macchina possono coesistere in un singolo flusso Meddle.

ModbusReader (macchina 1) ──┐
ModbusReader (macchina 2) ──┼─→ Merge → Reshape → OEE → Chart (gauge)
ModbusReader (macchina 3) ──┘ └→ InfluxDb2Writer
  1. ModbusReader (×N): Estrae contatori da ogni macchina
  2. Merge: Combina payload chiavati per ID macchina
  3. Reshape: Normalizza i nomi dei campi per corrispondere alla configurazione OEE
  4. OEE: Calcola l’OEE per ogni istanza macchina
  5. Chart: Renderizza il gauge con stile red, yellow, target
  6. InfluxDb2Writer: Persiste l’OEE per il trending storico
OpcuaReader → OEE → Isa182 (allarme su OEE < 0.5) → Alert (email)

Attiva una notifica quando l’OEE sostenuto scende sotto il 50% — utile per rilevare sottoperformance cronica.

  • Chart - Renderizza il gauge dall’output OEE
  • ISA-18.2 - Attiva allarmi su OEE basso
  • Reshape - Normalizza i nomi dei campi dei contatori
  • InfluxDB v2 - Persiste l’OEE per il trending
  • Transform - Calcola delta da contatori non monotonici