[
    {
        "id": "ef921bda80a01d07",
        "type": "tab",
        "label": "OEE Calculator for CNC",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "19c98b0c9970b7bd",
        "type": "mqtt in",
        "z": "ef921bda80a01d07",
        "name": "Read cnc01",
        "topic": "api/v1/reads/cnc01",
        "qos": "0",
        "datatype": "auto",
        "broker": "8ba9fcf3f855f0d2",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 530,
        "y": 360,
        "wires": [
            [
                "e9346e68dccf8f2e"
            ]
        ]
    },
    {
        "id": "e9346e68dccf8f2e",
        "type": "json",
        "z": "ef921bda80a01d07",
        "name": "Parse JSON",
        "property": "payload",
        "action": "",
        "pretty": false,
        "x": 740,
        "y": 360,
        "wires": [
            [
                "df0da63d6fd2962b"
            ]
        ]
    },
    {
        "id": "df0da63d6fd2962b",
        "type": "function",
        "z": "ef921bda80a01d07",
        "name": "OEE Calculation (A·P·Q)",
        "func": "// Get the data object\nconst root = msg.payload || {};\nconst d = root.data || root;\nconst timestamp = root.timestamp;\nconst deviceDisplayName = root.deviceDisplayName;\n\n// Read data using default values\nconst ok_pieces = Number(d.ok_pieces) || 0;\nconst total_pieces = Number(d.total_pieces) || 0;\nconst cycle_time = Number(d.cycle_time) || 0;\nconst ideal_cycle_time = Number(d.ideal_cycle_time) || 0;\nconst status = (d.status || \"\").toUpperCase();\n\n// Availability: 1 if it is producing; 0 otherwise (ALARM/STOP/IDLE/etc.)\nlet availability = 0;\nif ([\"RUN\", \"PROD\", \"PRODUCCION\"].includes(status)) {\n    availability = 1;\n}\n\n// Performance: ideal_cycle_time / cycle_time (maximum 1)\nlet performance = 0;\nif (cycle_time > 0 && ideal_cycle_time > 0) {\n    performance = Math.min(1, ideal_cycle_time / cycle_time);\n}\n\n// Quality: OK pieces / Total pieces\nlet quality = 0;\nif (total_pieces > 0) {\n    quality = ok_pieces / total_pieces;\n}\n\nconst oee = availability * performance * quality;\n\nmsg.payload = {\n    deviceDisplayName: deviceDisplayName + '_oee',\n    timestamp: timestamp,\n    error: false,\n    errorDescription: \"\",\n    data: {\n        availability: Number(availability.toFixed(4)),\n        performance: Number(performance.toFixed(4)),\n        quality: Number(quality.toFixed(4)),\n        OEE: Number((oee * 100).toFixed(2)),\n        accumulated_stops: d.accumulated_stops,\n        alarm_code: d.alarm_code,\n        cycle_time: cycle_time,\n        energy_consumption: d.energy_consumption,\n        ideal_cycle_time: ideal_cycle_time,\n        machine_id: d.machine_id,\n        nok_pieces: d.nok_pieces,\n        ok_pieces: ok_pieces,\n        order_id: d.order_id,\n        spindle_temperature: d.spindle_temperature,\n        status: status,\n        total_pieces: total_pieces,\n        vibration_rms: d.vibration_rms\n    }\n};\n\nmsg.topic = `api/v1/metrics/${deviceDisplayName}`;\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 970,
        "y": 360,
        "wires": [
            [
                "e6764c4236c1cf95",
                "d332f5af16243d9a"
            ]
        ]
    },
    {
        "id": "e6764c4236c1cf95",
        "type": "mqtt out",
        "z": "ef921bda80a01d07",
        "name": "Publish OEE",
        "topic": "",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "8ba9fcf3f855f0d2",
        "x": 1190,
        "y": 340,
        "wires": []
    },
    {
        "id": "d332f5af16243d9a",
        "type": "debug",
        "z": "ef921bda80a01d07",
        "name": "Debug OEE",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1200,
        "y": 400,
        "wires": []
    },
    {
        "id": "8ba9fcf3f855f0d2",
        "type": "mqtt-broker",
        "name": "",
        "broker": "mqttbbr",
        "port": "8883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": 4,
        "keepalive": 60,
        "cleansession": true,
        "autoUnsubscribe": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthRetain": "false",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closeRetain": "false",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willRetain": "false",
        "willPayload": "",
        "willMsg": {},
        "userProps": "",
        "sessionExpiry": ""
    }
]