OEE Calculations

OEE Dashboard Calculations:
Number of cycles = Last Cycle Number - Start Cycle Number
Device Status can be -
[No Device Status, Off, Running, Idle, Changeover, Maintenance, Defect/Fault]

Ideal Production Amount = Sum of all different status time duration
Actual Production Time = Total Running Time Duration
Availabillity Losses = Sum of [No Device Status, Off, Idle, Defect/Fault] status time duration
No planned production time = Sum of [Maintenance, Changeover] status time duration
=============
To calculate Availability, Quality and Performance -
Availability % = (Potential Production Time) / (Theoretical Production Time) * 100
For Example -
Potential Production Time = 20 hours
Theoretical Production Time = 24 hours
Availability % = 20/24 * 100 = 83.33 %
Quality % = (Good Parts Produced) / (Total Parts Produced) * 100
For Example -
Good Parts Produced = 2880
Total Parts Produced = 3000
Quality % = 2880/3000 * 100 = 96%
Performance % = (Total Parts Produced) / (Expected Parts Production) * 100
For Example -
Total Parts Produced = 3000 parts
Expected Parts Production = 3500 parts
Performance % = 3000/3500 * 100 = 85.71%
OEE % = Availability * Quality * Performance
For example
OEE % = (0.83 * 0.96 * 0.85 ) * 100 = 67.72 %
===============================================
Flux Query to get the total time duration of different device status
import "strings"
statuses = ["running", "off", "idle", "changeover", "maintenance", "defect/fault"]
data = from(bucket: "First-test-bucket")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "4C11AEE15B5C-events")
|> filter(fn: (r) => r["_field"] == "message")
|> filter(fn: (r) => strings.containsStr(v: r._value, substr: "running")
or strings.containsStr(v: r._value, substr: "off")
or strings.containsStr(v: r._value, substr: "idle")
or strings.containsStr(v: r._value, substr: "changeover")
or strings.containsStr(v: r._value, substr: "maintenance")
or strings.containsStr(v: r._value, substr: "defect/fault"))
|> map(fn: (r) => ({r with _status: if strings.containsStr(v: r._value, substr: "running") then "running"
else if strings.containsStr(v: r._value, substr: "off") then "off"
else if strings.containsStr(v: r._value, substr: "idle") then "idle"
else if strings.containsStr(v: r._value, substr: "changeover") then "changeover"
else if strings.containsStr(v: r._value, substr: "maintenance") then "maintenance"
else "defect/fault"}))
|> elapsed(unit: 1s)
|> group(columns: ["_status"])
|> sum(column: "elapsed")
|> map(fn: (r) => ({r with total_duration_seconds: r.elapsed}))
|> drop(columns: ["elapsed"])
data
|> pivot(rowKey:[], columnKey:["_status"], valueColumn: "total_duration_seconds")
|> map(fn: (r) => ({
running: if exists r.running then r.running else 0,
off: if exists r.off then r.off else 0,
idle: if exists r.idle then r.idle else 0,
changeover: if exists r.changeover then r.changeover else 0,
maintenance: if exists r.maintenance then r.maintenance else 0,
defect_fault: if exists r.defect_fault then r.defect_fault else 0
}))