Ir al contenido

Conector OEE

El conector OEE (Overall Equipment Effectiveness) calcula el KPI canónico de manufactura SEMI E10 a partir de contadores acumulativos de producción que llegan en el flujo de entrada. Emite el OEE por bloque más las tres métricas componentes (Disponibilidad, Rendimiento, Calidad) para que puedan renderizarse como medidores, gráficos o almacenarse en una base de datos de series temporales.

Tipos de Conector:

  • OEE - Procesador con estado que calcula el OEE sobre una ventana deslizante o por turno

El OEE se calcula como:

OEE = Disponibilidad × Rendimiento × Calidad

Donde:

  • Disponibilidad = runTime / plannedProductionTime
  • Rendimiento = (idealCycleTime × totalCount) / runTime
  • Calidad = goodCount / totalCount

Los tres se acotan a [0, 1].

  • ✅ Dos modos de ventana: sliding (basada en tiempo) y shift (delimitada por HH:MM)
  • ✅ Acumulación automática cuando RunTime / PlannedProductionTime no son proporcionados por el dispositivo
  • ✅ Acepta running como un campo de estado booleanoide (true/false, 1/0, on/off, yes/no, etc.)
  • ✅ Umbrales configurables (red, yellow) y target para el estilo del medidor
  • ✅ Emite una carga N/A (oee.* omitido) cuando una ventana tiene datos insuficientes
  • ✅ Espacio de nombres por ID de bloque para que varias instancias de OEE puedan escribir en la misma carga
  • ✅ Parseo numérico flexible — las cadenas se parsean automáticamente como floats

Ventana Deslizante con Contadores Reportados por el Dispositivo

Sección titulada «Ventana Deslizante con Contadores Reportados por el 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
}
}

Ventana de Turno con Bandera de Estado y Tiempo de Ciclo Literal

Sección titulada «Ventana de Turno con Bandera de Estado y Tiempo de Ciclo Literal»
{
"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
}
}

El objeto fields nombra las claves de la carga que el conector lee de cada muestra entrante.

{
"fields": {
"plannedProductionTime": "planned_time_s",
"runTime": "run_time_s",
"running": "machine_running",
"idealCycleTime": "ideal_cycle_s",
"totalCount": "parts_total",
"goodCount": "parts_good"
}
}
Campo¿Obligatorio?Notas
plannedProductionTimeOpcionalSegundos acumulativos. Si se omite, el conector acumula segundos de reloj desde la primera muestra
runTimeSe requiere uno de runTime / runningSegundos acumulativos que la máquina estuvo funcionando
runningSe requiere uno de runTime / runningEstado booleanoide; integrado internamente
idealCycleTimeSe requiere uno de idealCycleTime / idealCycleTimeSecondsSegundos por pieza a velocidad ideal
totalCountObligatorioConteo acumulativo de piezas intentadas
goodCountObligatorioConteo acumulativo de piezas buenas

Cuando el dispositivo no publica el tiempo de ciclo ideal, puedes declararlo como constante:

{
"idealCycleTimeSeconds": 4.5
}

Es mutuamente excluyente con fields.idealCycleTime.

{
"windowMode": "sliding"
}
  • sliding - Calcula los deltas sobre una ventana de tiempo móvil de longitud windowSeconds
  • shift - Calcula los deltas desde el comienzo del turno actual, definido por shiftStart, shiftEnd y timezone opcional
{
"windowSeconds": 3600
}

Obligatorio para windowMode: sliding. Debe ser > 0.

Valores recomendados:

  • Medidor en tiempo real: 300-900 (5-15 minutos)
  • Tendencia hora a hora: 3600 (1 hora)
  • Suavizado a largo plazo: 28800 (8 horas)

Obligatorio para windowMode: shift:

{
"shiftStart": "06:00",
"shiftEnd": "14:00",
"timezone": "Europe/Rome"
}
  • shiftStart / shiftEnd - Formato HH:MM en 24 horas
  • timezone - Identificador de zona horaria IANA (ej. Europe/Rome, America/New_York, Asia/Tokyo). Por defecto UTC si se omite
  • Los turnos nocturnos están soportados (ej. 22:0006:00)

Indicaciones de estilo emitidas junto a los valores de OEE para que los dashboards puedan colorear los medidores de forma consistente:

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

Restricciones:

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

Cada salida está espaciada por el ID de bloque de la instancia del conector OEE (auto-inyectado por 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
}

Cuando la ventana aún no tiene suficientes datos (ej. menos de dos snapshots en modo sliding, o el turno acaba de empezar), las claves oee/availability/performance/quality se omiten y sólo se emiten las claves de estilo del medidor. Esta es la carga N/A.

DataPayload (contadores acumulativos) → OEE → DataPayload (oee.<blockId>, etc.)

Ejemplo (ventana deslizante, 60s):

Flujo de entrada:

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

Después de la tercera muestra:

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

Salida:

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

Mejor para dashboards de operador en vivo donde el medidor responde a la actividad reciente:

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

La Salida Tiene Sólo Campos de Estilo del Medidor (Sin oee.*)

Sección titulada «La Salida Tiene Sólo Campos de Estilo del Medidor (Sin oee.*)»

Problema: Se está emitiendo la carga N/A

Soluciones:

  1. Modo sliding: requiere al menos 2 snapshots en la ventana. Espera una segunda muestra
  2. Modo shift: devuelve N/A cuando la hora actual está fuera de [shiftStart, shiftEnd]
  3. Arranque del modo shift: la primera muestra dentro del turno establece la línea base; el OEE aparecerá a partir de la segunda muestra

Problema: Se reporta un error con deltas iguales a 0 o negativos

Soluciones:

  1. Los contadores deben ser monótonamente crecientes. Si el dispositivo los reinicia (ej. al cambiar de turno), envuelve la entrada en un Transform para convertir a deltas primero, o divide la instancia de OEE por turno
  2. Confirma que los nombres de campos mapean a valores distintos de cero
  3. Si la ventana es muy corta (windowSeconds: 10) y la línea está inactiva, los deltas pueden ser exactamente cero; amplía la ventana

Problema: Errores invalid value for "..."

Soluciones:

  1. Los valores deben ser números finitos no negativos. NaN, infinito y negativos se rechazan
  2. Las cadenas se toleran sólo si se parsean a un float finito no negativo
  3. Si tu fuente emite booleanos para “running”, asegúrate de que el campo running — no runTime — esté configurado

Problema: OEE sospechosamente perfecto

Soluciones:

  1. Comprueba que idealCycleTime sea realista. Un ideal excesivamente lento hace que el Rendimiento sea ≥ 1, lo que se acota a 1
  2. Verifica que runTime < plannedProductionTime. Si son idénticos, la Disponibilidad es 1.0

Zona Horaria Incorrecta para los Límites de Turno

Sección titulada «Zona Horaria Incorrecta para los Límites de Turno»

Problema: Los inicios/finales de turno están desfasados N horas

Soluciones:

  1. Define siempre timezone con un nombre IANA válido
  2. No uses notaciones de offset como +02:00 — se rechazan

1. Prefiere los Contadores Reportados por el Dispositivo Cuando Estén Disponibles

Sección titulada «1. Prefiere los Contadores Reportados por el Dispositivo Cuando Estén Disponibles»

Si el PLC publica runTime y plannedProductionTime como segundos acumulativos, úsalos directamente. El acumulador interno es un fallback para dispositivos que sólo publican una bandera running.

  • Operadores: ventana deslizante de 5-15 minutos
  • Supervisores: ventana por turno
  • Ejecutivos: agregación por día o por semana (descendente)

La definición ISO es “tiempo de ciclo sostenible más rápido”, no “folleto de marketing”. Un valor optimista deprime el Rendimiento e infravalora el OEE real.

4. Combínalo con Filter o Transform Aguas Arriba

Sección titulada «4. Combínalo con Filter o Transform Aguas Arriba»

Si tu flujo crudo contiene cargas no relacionadas, usa Filter para mantener sólo las actualizaciones de contador antes del bloque OEE.

Cada instancia del conector OEE está espaciada por blockId, así que los dashboards multi-máquina pueden coexistir en un único flujo de Meddle.

Pipeline Completo de Dashboard de Producción

Sección titulada «Pipeline Completo de Dashboard de Producción»
ModbusReader (máquina 1) ──┐
ModbusReader (máquina 2) ──┼─→ Merge → Reshape → OEE → Chart (medidor)
ModbusReader (máquina 3) ──┘ └→ InfluxDb2Writer
  1. ModbusReader (×N): Extrae contadores de cada máquina
  2. Merge: Combina cargas con clave por ID de máquina
  3. Reshape: Normaliza los nombres de campo para que coincidan con la configuración del OEE
  4. OEE: Calcula el OEE por instancia de máquina
  5. Chart: Renderiza el medidor con el estilo red, yellow, target
  6. InfluxDb2Writer: Persiste el OEE para tendencias históricas
OpcuaReader → OEE → Isa182 (alarma si OEE < 0.5) → Alert (email)

Activa una notificación cuando el OEE sostenido cae por debajo del 50% — útil para detección de bajo rendimiento crónico.

  • Chart - Renderiza el medidor desde la salida del OEE
  • ISA-18.2 - Dispara alarmas con OEE bajo
  • Reshape - Normaliza los nombres de campo de contadores
  • InfluxDB v2 - Persiste el OEE para tendencias
  • Transform - Calcula deltas de contadores no monótonos