Rela AIRela AI Docs
OEE

Accuratezza dell'OEE

Come Rela-ai filtra i bias strutturali (sensori morti, PLC condivisi, downtime fabbricato) perché l'OEE rifletta l'operatività reale — non un numero cosmetico.

Accuratezza dell'OEE

L'OEE mostrato da una dashboard è utile solo se riflette la realtà. Un audit ha fatto emergere diversi punti in cui il calcolo tradizionale si discosta dall'operatività reale: downtime inventato da euristiche, sensori morti che producono un falso 0%, PLC condivisi che gonfiano le metriche per doppio conteggio, calibrazione rotta nascosta sotto un cap del 100%. Questa pagina documenta ciascuno di quei punti e come sono stati chiusi.

A cosa serve

  • Sapere se il numero di OEE che guardi è affidabile o contaminato da config errata.
  • Auditare il calcolo punto per punto rispetto allo standard Nakajima.
  • Individuare sensori morti o PLC condivisi che gonfiano/sgonfiano il numero silenziosamente.

Come funziona

Ogni fonte di bias è chiusa da un filtro esplicito e un flag nella risposta JSON. Se il calcolo è colpito, la risposta lo dice: status=stale_source, downtime_estimation=true, performance_capped=true. L'operatore vede il numero E sa se fidarsi.

Sintesi esecutiva

OEE verificabile: ogni deviazione dallo standard Nakajima è coperta da un filtro esplicito e da un flag nella risposta. L'operatore vede la realtà — incluso quando la realtà è contaminata da config errata.

PrimaAdesso
Downtime fisso 5 min per evento (fermo di 2h riportato come 5 min)Durata reale da metadata.duration_seconds + flag downtime_estimation
Sensore morto poi OEE=0% falsoFiltro di staleness + status=stale_source
PLC condiviso tra linee poi conteggio doppioScope per asset_id nel $match
Performance > 100% capato in silenzioperformance_pct_raw + flag performance_capped
Buffer/store-and-forward disallineava i periodimetadata.timestamp su created_at
Config orfana (asset/source cancellato)Validazione 404 su configure
Cambi di soglia riscrivevano lo storico senza tracciaAudit trail fire-and-forget
Turni e PM affossavano availabilityshift_pattern + subtract_scheduled_maintenance
Trend troncato su un errore transitorioLoop robusto + finestre di giorno calendariale
Nessun Pareto né version stampdowntime_breakdown + config_version

Findings chiusi

Critici (H)

OEE-H1 — Durata reale del downtime

Il calcolo legacy usava 5 min per evento di downtime indipendentemente dalla durata reale. Un fermo di 2 ore riportato come singolo evento contava 5 min; un fermo di 10 secondi con 12 rimbalzi contava 60 min. La Disponibilità risultante era casuale rispetto alla realtà.

Il resolver segue ora una priorità:

  1. Somma di metadata.duration_seconds (prima classe, misurato).
  2. Somma di metadata.duration_minutes (scorciatoia di comodità).
  3. Euristica legacy 5 min × conteggio eventi (retrocompatibile, segnalata).

La risposta porta downtime_estimation con measured, heuristic o none così la dashboard può avvisare quando il numero è approssimato.

{
  "downtime_minutes": 90.0,
  "downtime_estimation": "measured"
}

OEE-H2 — Guardia di staleness sul count source

Una sorgente di conteggio contrassegnata stale dal sensor_watchdog non alimenta più il calcolo. Al suo posto la risposta esegue short-circuit con status="stale_source" e un messaggio che rimanda al watchdog. Previene un OEE=0% falso quando il sensore è morto ma la linea sta ancora producendo.

{
  "status": "stale_source",
  "message": "Count source is stale; OEE not computed."
}

OEE-H3 — Scope per asset_id

Quando due asset condividono lo stesso count_source_id (tipico: due linee dietro lo stesso PLC), ogni evento veniva conteggiato una volta per asset — Rendimento e Qualità gonfiati simmetricamente, downtime raddoppiato. Il $match include ora una clausola $or che accetta eventi con asset_id alla radice, dentro metadata, o assente (single-asset legacy).

OEE-H4 — Performance reale + performance_capped

performance > 100% non è un glitch — è un segnale forte di calibrazione rotta (cycle_time sotto-configurato o doppio conteggio). Il codice legacy capava silenziosamente al 100%. La risposta ora espone entrambi:

{
  "performance_pct": 100.0,
  "performance_pct_raw": 173.6,
  "performance_capped": true
}

Il KPI di OEE continua a usare il valore capato (Nakajima definisce 0-100), ma la dashboard può mostrare un badge "calibrazione da rivedere" quando raw > 100.

Medi (M)

OEE-M1 — Timestamp reale vs created_at

Il $match preferisce metadata.timestamp (ISO) quando l'evento lo porta; created_at è il fallback. Corregge il bias del buffer/store-and-forward: una lettura partita alle 14:00 ma re-ingerita alle 14:45 ora cade nel bucket delle 14:00, non 14:45.

OEE-M2 — shift_pattern per giorno

Nuovo campo di config:

{
  "shift_pattern": {
    "hours_by_weekday": {"1": 8, "2": 8, "3": 8, "4": 8, "5": 8}
  }
}

ISO weekday: 1=lunedì, 7=domenica. Uno stabilimento che gira Lun-Ven 8h ed è fermo nei weekend vede planned=0 min il sabato, non 0% OEE contro un piano fantasma da 480 min.

OEE-M3 — PM pianificata sottrae da planned

Nuovo flag subtract_scheduled_maintenance: true (default). I _maintenance_plans con next_due_at nel periodo riducono planned_minutes invece di contare come downtime. Una PM di 4h in un turno di 8h non riporta più Availability=50% (come se la PM fosse un guasto); planned diventa 240 min e Availability resta 100% per le restanti 4h di produzione reale. Opt-out disponibile per i tenant la cui convenzione di audit interno tiene la PM nel bucket di downtime.

OEE-M4 — Validazione di asset_id + count_source_id

POST /configure restituisce 404 quando asset_id non esiste (né come ObjectId di _assets._id né come asset_code) o quando count_source_id non è in _machine_event_sources. Previene config orfane che producono un OEE=0% silenzioso quando l'asset o la sorgente sono stati cancellati.

OEE-M5 — Audit trail sulle mutazioni della config

Qualsiasi modifica ai 6 campi regolati (planned_production_hours, ideal_cycle_time_seconds, count_source_id, count_metric_field, reject_metric_field, downtime_event_type) scrive una entry in _audit_trail con actor, timestamp, snapshot precedente e nuovo. Un auditor può rispondere "chi ha spostato ideal_cycle_time_seconds da 2.5 a 3.0 il 3 marzo".

OEE-M6 — Trend robusto agli errori transitori

Un errore transitorio in DB (es. un timeout al giorno 3 di un trend di 7 giorni) non tronca più il risultato. Ogni giorno computa in un proprio try/except; i fallimenti restituiscono {"date": "...", "status": "error"} come segnaposto e il loop prosegue. Solo un 404 (not-configured) è terminale, perché è un errore di config, non transitorio.

OEE-M7 — Finestre di giorno calendariale

Le finestre del trend sono ancorate alla mezzanotte UTC (00:00 to 24:00) anziché a finestre rotolanti di 24h ancorate al momento della chiamata. L'etichetta "2026-04-17" ora corrisponde esattamente alla finestra che rappresenta.

Bassi (L)

OEE-L2 — Breakdown Pareto del downtime

Nuova lista downtime_breakdown nella risposta, raggruppata per event_type e ordinata decrescente per minuti:

{
  "downtime_breakdown": [
    {"event_type": "STOP_COMPRESSOR", "event_count": 2, "minutes": 40.0},
    {"event_type": "STOP_CHANGEOVER", "event_count": 3, "minutes": 20.0}
  ]
}

Risponde "quale tipo di fermo ci è costato più tempo?" senza una seconda query.

OEE-L3 — config_version nella risposta

Ogni configure_oee fa $inc.config_version su MongoDB. Ogni calculate_oee stampa il config_version attivo nella risposta. Un valore OEE storico è ancorato al set di soglie che lo ha prodotto — la domanda d'audit "con quale config è stato calcolato quell'87%?" è banalmente risolvibile.

Struttura completa della risposta

{
  "asset_id": "line-01",
  "oee_pct": 72.3,
  "availability_pct": 93.8,
  "performance_pct": 85.0,
  "performance_pct_raw": 85.0,
  "performance_capped": false,
  "quality_pct": 98.2,
  "total_count": 4800,
  "good_count": 4714,
  "reject_count": 86,
  "planned_minutes": 480.0,
  "operating_minutes": 450.0,
  "downtime_minutes": 30.0,
  "downtime_estimation": "measured",
  "downtime_breakdown": [
    {"event_type": "STOP_COMPRESSOR", "event_count": 2, "minutes": 22.0},
    {"event_type": "STOP_CHANGEOVER", "event_count": 1, "minutes": 8.0}
  ],
  "scheduled_maintenance_minutes": 0.0,
  "config_version": 7,
  "period_start": "2026-04-17T00:00:00+00:00",
  "period_end": "2026-04-18T00:00:00+00:00"
}

Collection MongoDB toccate

CollectionUso
_oee_configsConfig per-asset con config_version monotonico.
_machine_eventsSorgente unica di eventi (produzione + downtime) filtrata per asset_id + timestamp reale.
_machine_event_sourcesStato connected/stale letto dal guard di OEE-H2.
_assetsValidazione di asset_id su configure (dual-lookup: ObjectId o asset_code).
_maintenance_plansFinestre pianificate che riducono planned_minutes (OEE-M3).
_audit_trailEntry fire-and-forget con action=oee_config_updated.

Benefici chiave

  • Decisioni su dati reali, non euristiche.
  • Zero OEE=0% falso da sensori morti.
  • Zero doppio conteggio tra linee che condividono un PLC.
  • Calibrazione visibile: performance_pct_raw > 100 scatena revisione.
  • Trend stabile: etichette e finestre allineate, errori transitori non troncano.
  • Audit-ready: ogni mutazione di soglia lascia traccia, ogni KPI storico porta il suo config_version.

In questa pagina